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 fnPCSCSCardEstablishContext pfnSCardEstablishContext;
178 fnPCSCSCardReleaseContext pfnSCardReleaseContext;
179 fnPCSCSCardIsValidContext pfnSCardIsValidContext;
180 fnPCSCSCardConnect pfnSCardConnect;
181 fnPCSCSCardReconnect pfnSCardReconnect;
182 fnPCSCSCardDisconnect pfnSCardDisconnect;
183 fnPCSCSCardBeginTransaction pfnSCardBeginTransaction;
184 fnPCSCSCardEndTransaction pfnSCardEndTransaction;
185 fnPCSCSCardStatus pfnSCardStatus;
186 fnPCSCSCardGetStatusChange pfnSCardGetStatusChange;
187 fnPCSCSCardControl pfnSCardControl;
188 fnPCSCSCardTransmit pfnSCardTransmit;
189 fnPCSCSCardListReaderGroups pfnSCardListReaderGroups;
190 fnPCSCSCardListReaders pfnSCardListReaders;
191 fnPCSCSCardFreeMemory pfnSCardFreeMemory;
192 fnPCSCSCardCancel pfnSCardCancel;
193 fnPCSCSCardGetAttrib pfnSCardGetAttrib;
194 fnPCSCSCardSetAttrib pfnSCardSetAttrib;
208 SCARDCONTEXT hContext;
209 DWORD dwCardHandleCount;
210 BOOL isTransactionLocked;
217 SCARDCONTEXT hSharedContext;
220static HMODULE g_PCSCModule =
nullptr;
221static PCSCFunctionTable g_PCSC = WINPR_C_ARRAY_INIT;
223static HANDLE g_StartedEvent =
nullptr;
224static int g_StartedEventRefCount = 0;
226static BOOL g_SCardAutoAllocate = FALSE;
227static BOOL g_PnP_Notification = TRUE;
230static unsigned int OSXVersion = 0;
233static wListDictionary* g_CardHandles =
nullptr;
234static wListDictionary* g_CardContexts =
nullptr;
235static wListDictionary* g_MemoryBlocks =
nullptr;
237static const char SMARTCARD_PNP_NOTIFICATION_A[] =
"\\\\?PnP?\\Notification";
246static LONG WINAPI PCSC_SCardFreeMemory_Internal(SCARDCONTEXT hContext, LPVOID pvMem);
247static LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope, LPCVOID pvReserved1,
249 LPSCARDCONTEXT phContext);
250static LONG WINAPI PCSC_SCardReleaseContext_Internal(SCARDCONTEXT hContext);
252static LONG PCSC_SCard_LogError(
const char* what)
254 WLog_WARN(TAG,
"Missing function pointer %s=nullptr", what);
255 return SCARD_E_UNSUPPORTED_FEATURE;
258static LONG PCSC_MapErrorCodeToWinSCard(PCSC_LONG errorCode)
268 if (errorCode != SCARD_S_SUCCESS)
270 if (errorCode == SCARD_E_UNEXPECTED)
271 errorCode = SCARD_E_UNSUPPORTED_FEATURE;
274 return (LONG)errorCode;
277static DWORD PCSC_ConvertCardStateToWinSCard(DWORD dwCardState, PCSC_LONG status)
295 if (status == SCARD_S_SUCCESS)
297 if ((dwCardState & PCSC_SCARD_NEGOTIABLE) || (dwCardState & PCSC_SCARD_SPECIFIC))
298 return SCARD_SPECIFIC;
301 if (dwCardState & PCSC_SCARD_POWERED)
302 return SCARD_POWERED;
304 if (dwCardState & PCSC_SCARD_NEGOTIABLE)
305 return SCARD_NEGOTIABLE;
307 if (dwCardState & PCSC_SCARD_SPECIFIC)
308 return SCARD_SPECIFIC;
310 if (dwCardState & PCSC_SCARD_ABSENT)
313 if (dwCardState & PCSC_SCARD_PRESENT)
314 return SCARD_PRESENT;
316 if (dwCardState & PCSC_SCARD_SWALLOWED)
317 return SCARD_SWALLOWED;
319 if (dwCardState & PCSC_SCARD_UNKNOWN)
320 return SCARD_UNKNOWN;
322 return SCARD_UNKNOWN;
325static DWORD PCSC_ConvertProtocolsToWinSCard(PCSC_DWORD dwProtocols)
331 if (dwProtocols & PCSC_SCARD_PROTOCOL_RAW)
333 dwProtocols &= ~PCSC_SCARD_PROTOCOL_RAW;
334 dwProtocols |= SCARD_PROTOCOL_RAW;
337 if (dwProtocols & PCSC_SCARD_PROTOCOL_T15)
339 dwProtocols &= ~PCSC_SCARD_PROTOCOL_T15;
342 return (DWORD)dwProtocols;
345static DWORD PCSC_ConvertProtocolsFromWinSCard(DWORD dwProtocols)
351 if (dwProtocols & SCARD_PROTOCOL_RAW)
353 dwProtocols &= ~SCARD_PROTOCOL_RAW;
354 dwProtocols |= PCSC_SCARD_PROTOCOL_RAW;
357 if (dwProtocols & SCARD_PROTOCOL_DEFAULT)
359 dwProtocols &= ~SCARD_PROTOCOL_DEFAULT;
362 if (dwProtocols == SCARD_PROTOCOL_UNDEFINED)
364 dwProtocols = SCARD_PROTOCOL_Tx;
370static PCSC_SCARDCONTEXT* PCSC_GetCardContextData(SCARDCONTEXT hContext)
372 PCSC_SCARDCONTEXT* pContext =
nullptr;
377 pContext = (PCSC_SCARDCONTEXT*)ListDictionary_GetItemValue(g_CardContexts, (
void*)hContext);
385static void pcsc_cache_item_free(
void* ptr)
387 PCSC_CACHE_ITEM* data = ptr;
393static PCSC_SCARDCONTEXT* PCSC_EstablishCardContext(SCARDCONTEXT hContext)
395 PCSC_SCARDCONTEXT* pContext =
nullptr;
396 pContext = (PCSC_SCARDCONTEXT*)calloc(1,
sizeof(PCSC_SCARDCONTEXT));
401 pContext->hContext = hContext;
403 if (!InitializeCriticalSectionAndSpinCount(&(pContext->lock), 4000))
406 pContext->cache = HashTable_New(FALSE);
407 if (!pContext->cache)
409 if (!HashTable_SetupForStringData(pContext->cache, FALSE))
412 wObject* obj = HashTable_ValueObject(pContext->cache);
418 g_CardContexts = ListDictionary_New(TRUE);
424 if (!ListDictionary_Add(g_CardContexts, (
void*)hContext, (
void*)pContext))
429 HashTable_Free(pContext->cache);
430 DeleteCriticalSection(&(pContext->lock));
436static void PCSC_ReleaseCardContext(SCARDCONTEXT hContext)
438 PCSC_SCARDCONTEXT* pContext =
nullptr;
439 pContext = PCSC_GetCardContextData(hContext);
443 WLog_ERR(TAG,
"PCSC_ReleaseCardContext: null pContext!");
447 DeleteCriticalSection(&(pContext->lock));
448 HashTable_Free(pContext->cache);
454 ListDictionary_Remove(g_CardContexts, (
void*)hContext);
457static BOOL PCSC_LockCardContext(SCARDCONTEXT hContext)
459 PCSC_SCARDCONTEXT* pContext =
nullptr;
460 pContext = PCSC_GetCardContextData(hContext);
464 WLog_ERR(TAG,
"PCSC_LockCardContext: invalid context (%p)", (
void*)hContext);
468 EnterCriticalSection(&(pContext->lock));
472static BOOL PCSC_UnlockCardContext(SCARDCONTEXT hContext)
474 PCSC_SCARDCONTEXT* pContext =
nullptr;
475 pContext = PCSC_GetCardContextData(hContext);
479 WLog_ERR(TAG,
"PCSC_UnlockCardContext: invalid context (%p)", (
void*)hContext);
483 LeaveCriticalSection(&(pContext->lock));
487static PCSC_SCARDHANDLE* PCSC_GetCardHandleData(SCARDHANDLE hCard)
489 PCSC_SCARDHANDLE* pCard =
nullptr;
494 pCard = (PCSC_SCARDHANDLE*)ListDictionary_GetItemValue(g_CardHandles, (
void*)hCard);
502static SCARDCONTEXT PCSC_GetCardContextFromHandle(SCARDHANDLE hCard)
504 PCSC_SCARDHANDLE* pCard =
nullptr;
505 pCard = PCSC_GetCardHandleData(hCard);
510 return pCard->hSharedContext;
513static BOOL PCSC_WaitForCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard, BOOL shared)
516 PCSC_SCARDHANDLE* pCard =
nullptr;
517 PCSC_SCARDCONTEXT* pContext =
nullptr;
522 pContext = PCSC_GetCardContextData(hContext);
527 if (!pContext->owner)
534 pCard = PCSC_GetCardHandleData(hCard);
539 shared = pCard->shared;
540 hContext = pCard->hSharedContext;
541 pContext = PCSC_GetCardContextData(hContext);
546 if (!pContext->owner)
550 pContext->owner = hCard;
555 if (pContext->owner == hCard)
567static BOOL PCSC_ReleaseCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard)
569 PCSC_SCARDHANDLE* pCard =
nullptr;
570 PCSC_SCARDCONTEXT* pContext =
nullptr;
575 pContext = PCSC_GetCardContextData(hContext);
580 hCard = pContext->owner;
585 pCard = PCSC_GetCardHandleData(hCard);
595 pCard = PCSC_GetCardHandleData(hCard);
600 hContext = pCard->hSharedContext;
601 pContext = PCSC_GetCardContextData(hContext);
606 if (pContext->owner == hCard)
615static PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hSharedContext, SCARDHANDLE hCard)
617 PCSC_SCARDHANDLE* pCard =
nullptr;
618 PCSC_SCARDCONTEXT* pContext =
nullptr;
619 pContext = PCSC_GetCardContextData(hSharedContext);
623 WLog_ERR(TAG,
"PCSC_ConnectCardHandle: null pContext!");
627 pCard = (PCSC_SCARDHANDLE*)calloc(1,
sizeof(PCSC_SCARDHANDLE));
632 pCard->hSharedContext = hSharedContext;
636 g_CardHandles = ListDictionary_New(TRUE);
642 if (!ListDictionary_Add(g_CardHandles, (
void*)hCard, (
void*)pCard))
645 pContext->dwCardHandleCount++;
652static void PCSC_DisconnectCardHandle(SCARDHANDLE hCard)
654 PCSC_SCARDHANDLE* pCard =
nullptr;
655 PCSC_SCARDCONTEXT* pContext =
nullptr;
656 pCard = PCSC_GetCardHandleData(hCard);
661 pContext = PCSC_GetCardContextData(pCard->hSharedContext);
667 ListDictionary_Remove(g_CardHandles, (
void*)hCard);
671 WLog_ERR(TAG,
"PCSC_DisconnectCardHandle: null pContext!");
675 pContext->dwCardHandleCount--;
678static BOOL PCSC_AddMemoryBlock(SCARDCONTEXT hContext,
void* pvMem)
682 g_MemoryBlocks = ListDictionary_New(TRUE);
688 return ListDictionary_Add(g_MemoryBlocks, pvMem, (
void*)hContext);
691static void* PCSC_RemoveMemoryBlock(SCARDCONTEXT hContext,
void* pvMem)
693 WINPR_UNUSED(hContext);
698 return ListDictionary_Take(g_MemoryBlocks, pvMem);
705static LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope, LPCVOID pvReserved1,
707 LPSCARDCONTEXT phContext)
709 WINPR_UNUSED(dwScope);
710 PCSC_LONG status = SCARD_S_SUCCESS;
712 if (!g_PCSC.pfnSCardEstablishContext)
713 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardEstablishContext");
716 g_PCSC.pfnSCardEstablishContext(SCARD_SCOPE_SYSTEM, pvReserved1, pvReserved2, phContext);
717 return PCSC_MapErrorCodeToWinSCard(status);
720static LONG WINAPI PCSC_SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
721 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
725 status = PCSC_SCardEstablishContext_Internal(dwScope, pvReserved1, pvReserved2, phContext);
727 if (status == SCARD_S_SUCCESS)
728 PCSC_EstablishCardContext(*phContext);
733static LONG WINAPI PCSC_SCardReleaseContext_Internal(SCARDCONTEXT hContext)
735 PCSC_LONG status = SCARD_S_SUCCESS;
737 if (!g_PCSC.pfnSCardReleaseContext)
738 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardReleaseContext");
742 WLog_ERR(TAG,
"SCardReleaseContext: null hContext");
743 return PCSC_MapErrorCodeToWinSCard(status);
746 status = g_PCSC.pfnSCardReleaseContext(hContext);
747 return PCSC_MapErrorCodeToWinSCard(status);
750static LONG WINAPI PCSC_SCardReleaseContext(SCARDCONTEXT hContext)
752 LONG status = SCARD_S_SUCCESS;
754 status = PCSC_SCardReleaseContext_Internal(hContext);
756 if (status != SCARD_S_SUCCESS)
757 PCSC_ReleaseCardContext(hContext);
762static LONG WINAPI PCSC_SCardIsValidContext(SCARDCONTEXT hContext)
764 PCSC_LONG status = SCARD_S_SUCCESS;
766 if (!g_PCSC.pfnSCardIsValidContext)
767 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardIsValidContext");
769 status = g_PCSC.pfnSCardIsValidContext(hContext);
770 return PCSC_MapErrorCodeToWinSCard(status);
773static LONG WINAPI PCSC_SCardListReaderGroups_Internal(SCARDCONTEXT hContext, LPSTR mszGroups,
776 PCSC_LONG status = SCARD_S_SUCCESS;
777 BOOL pcchGroupsAlloc = FALSE;
778 PCSC_DWORD pcsc_cchGroups = 0;
781 return SCARD_E_INVALID_PARAMETER;
783 if (!g_PCSC.pfnSCardListReaderGroups)
784 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaderGroups");
786 if (*pcchGroups == SCARD_AUTOALLOCATE)
787 pcchGroupsAlloc = TRUE;
789 pcsc_cchGroups = pcchGroupsAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD)*pcchGroups;
791 if (pcchGroupsAlloc && !g_SCardAutoAllocate)
794 status = g_PCSC.pfnSCardListReaderGroups(hContext,
nullptr, &pcsc_cchGroups);
796 if (status == SCARD_S_SUCCESS)
798 LPSTR tmp = calloc(1, pcsc_cchGroups);
801 return SCARD_E_NO_MEMORY;
803 status = g_PCSC.pfnSCardListReaderGroups(hContext, tmp, &pcsc_cchGroups);
805 if (status != SCARD_S_SUCCESS)
811 PCSC_AddMemoryBlock(hContext, tmp);
813 *(LPSTR*)mszGroups = tmp;
818 status = g_PCSC.pfnSCardListReaderGroups(hContext, mszGroups, &pcsc_cchGroups);
821 *pcchGroups = (DWORD)pcsc_cchGroups;
822 return PCSC_MapErrorCodeToWinSCard(status);
825static LONG WINAPI PCSC_SCardListReaderGroupsA(SCARDCONTEXT hContext, LPSTR mszGroups,
828 LONG status = SCARD_S_SUCCESS;
830 if (!g_PCSC.pfnSCardListReaderGroups)
831 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaderGroups");
833 if (!PCSC_LockCardContext(hContext))
834 return SCARD_E_INVALID_HANDLE;
836 status = PCSC_SCardListReaderGroups_Internal(hContext, mszGroups, pcchGroups);
838 if (!PCSC_UnlockCardContext(hContext))
839 return SCARD_E_INVALID_HANDLE;
844static LONG WINAPI PCSC_SCardListReaderGroupsW(SCARDCONTEXT hContext, LPWSTR mszGroups,
847 LPSTR mszGroupsA =
nullptr;
848 LPSTR* pMszGroupsA = &mszGroupsA;
849 LONG status = SCARD_S_SUCCESS;
851 if (!g_PCSC.pfnSCardListReaderGroups)
852 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaderGroups");
854 if (!PCSC_LockCardContext(hContext))
855 return SCARD_E_INVALID_HANDLE;
857 status = PCSC_SCardListReaderGroups_Internal(hContext, (LPSTR)&mszGroupsA, pcchGroups);
859 if (status == SCARD_S_SUCCESS)
862 WCHAR* str = ConvertMszUtf8NToWCharAlloc(*pMszGroupsA, *pcchGroups, &size);
864 return SCARD_E_NO_MEMORY;
865 *(WCHAR**)mszGroups = str;
866 *pcchGroups = (DWORD)size;
867 PCSC_AddMemoryBlock(hContext, str);
868 PCSC_SCardFreeMemory_Internal(hContext, *pMszGroupsA);
871 if (!PCSC_UnlockCardContext(hContext))
872 return SCARD_E_INVALID_HANDLE;
877static LONG WINAPI PCSC_SCardListReaders_Internal(SCARDCONTEXT hContext, LPCSTR mszGroups,
878 LPSTR mszReaders, LPDWORD pcchReaders)
880 PCSC_LONG status = SCARD_S_SUCCESS;
881 BOOL pcchReadersAlloc = FALSE;
882 PCSC_DWORD pcsc_cchReaders = 0;
884 return SCARD_E_INVALID_PARAMETER;
886 if (!g_PCSC.pfnSCardListReaders)
887 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaders");
891 if (*pcchReaders == SCARD_AUTOALLOCATE)
892 pcchReadersAlloc = TRUE;
894 pcsc_cchReaders = pcchReadersAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD)*pcchReaders;
896 if (pcchReadersAlloc && !g_SCardAutoAllocate)
899 status = g_PCSC.pfnSCardListReaders(hContext, mszGroups,
nullptr, &pcsc_cchReaders);
901 if (status == SCARD_S_SUCCESS)
903 char* tmp = calloc(1, pcsc_cchReaders);
906 return SCARD_E_NO_MEMORY;
908 status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, tmp, &pcsc_cchReaders);
910 if (status != SCARD_S_SUCCESS)
916 PCSC_AddMemoryBlock(hContext, tmp);
918 *(
char**)mszReaders = tmp;
923 status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, mszReaders, &pcsc_cchReaders);
926 *pcchReaders = (DWORD)pcsc_cchReaders;
927 return PCSC_MapErrorCodeToWinSCard(status);
930static LONG WINAPI PCSC_SCardListReadersA(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders,
933 BOOL nullCardContext = FALSE;
934 LONG status = SCARD_S_SUCCESS;
936 if (!g_PCSC.pfnSCardListReaders)
937 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaders");
941 status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM,
nullptr,
nullptr, &hContext);
943 if (status != SCARD_S_SUCCESS)
946 nullCardContext = TRUE;
949 if (!PCSC_LockCardContext(hContext))
950 return SCARD_E_INVALID_HANDLE;
952 status = PCSC_SCardListReaders_Internal(hContext, mszGroups, mszReaders, pcchReaders);
954 if (!PCSC_UnlockCardContext(hContext))
955 return SCARD_E_INVALID_HANDLE;
959 status = PCSC_SCardReleaseContext(hContext);
965static LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext, LPCWSTR mszGroups,
966 LPWSTR mszReaders, LPDWORD pcchReaders)
968 LPSTR mszGroupsA =
nullptr;
969 LPSTR mszReadersA =
nullptr;
970 LONG status = SCARD_S_SUCCESS;
971 BOOL nullCardContext = FALSE;
973 if (!g_PCSC.pfnSCardListReaders)
974 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaders");
978 status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM,
nullptr,
nullptr, &hContext);
980 if (status != SCARD_S_SUCCESS)
983 nullCardContext = TRUE;
986 if (!PCSC_LockCardContext(hContext))
987 return SCARD_E_INVALID_HANDLE;
991 mszGroupsA = ConvertWCharToUtf8Alloc(mszGroups,
nullptr);
993 return SCARD_E_NO_MEMORY;
1001 cnv.ppc = &mszReadersA;
1003 status = PCSC_SCardListReaders_Internal(hContext, mszGroupsA, cnv.pc, pcchReaders);
1005 if (status == SCARD_S_SUCCESS)
1008 WCHAR* str = ConvertMszUtf8NToWCharAlloc(mszReadersA, *pcchReaders, &size);
1009 PCSC_SCardFreeMemory_Internal(hContext, mszReadersA);
1010 if (!str || (size > UINT32_MAX))
1011 return SCARD_E_NO_MEMORY;
1013 *(LPWSTR*)mszReaders = str;
1014 *pcchReaders = (DWORD)size;
1015 PCSC_AddMemoryBlock(hContext, str);
1018 if (!PCSC_UnlockCardContext(hContext))
1019 return SCARD_E_INVALID_HANDLE;
1021 if (nullCardContext)
1023 status = PCSC_SCardReleaseContext(hContext);
1033 const char* cardName;
1036static PcscKnownAtr knownAtrs[] = {
1038 { { 0x3B, 0xFD, 0x13, 0x00, 0x00, 0x81, 0x31, 0xFE, 0x15, 0x80, 0x73, 0xC0,
1039 0x21, 0xC0, 0x57, 0x59, 0x75, 0x62, 0x69, 0x4B, 0x65, 0x79, 0x40 },
1041 "NIST SP 800-73 [PIV]" },
1043 { { 0x3B, 0xFC, 0x18, 0x00, 0x00, 0x81, 0x31, 0x80, 0x45, 0x90, 0x67,
1044 0x46, 0x4A, 0x00, 0x64, 0x16, 0x06, 0xF2, 0x72, 0x7E, 0x00, 0xE0 },
1046 "PIVKey Feitian (E0)" }
1050#define ARRAY_LENGTH(a) (sizeof(a) / sizeof(a)[0])
1053static const char* findCardByAtr(LPCBYTE pbAtr)
1055 for (
size_t i = 0; i < ARRAY_LENGTH(knownAtrs); i++)
1057 if (memcmp(knownAtrs[i].atr, pbAtr, knownAtrs[i].atrLen) == 0)
1058 return knownAtrs[i].cardName;
1064static LONG WINAPI PCSC_SCardListCardsA(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, LPCBYTE pbAtr,
1065 LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount,
1066 CHAR* mszCards, LPDWORD pcchCards)
1068 const char* cardName =
nullptr;
1069 DWORD outputLen = 1;
1070 CHAR* output =
nullptr;
1071 BOOL autoAllocate = 0;
1073 if (!pbAtr || rgquidInterfaces || cguidInterfaceCount)
1074 return SCARD_E_UNSUPPORTED_FEATURE;
1077 return SCARD_E_INVALID_PARAMETER;
1079 autoAllocate = (*pcchCards == SCARD_AUTOALLOCATE);
1081 cardName = findCardByAtr(pbAtr);
1083 outputLen += strlen(cardName) + 1;
1085 *pcchCards = outputLen;
1088 output = malloc(outputLen);
1090 return SCARD_E_NO_MEMORY;
1092 *((LPSTR*)mszCards) = output;
1097 return SCARD_S_SUCCESS;
1099 if (*pcchCards < outputLen)
1100 return SCARD_E_INSUFFICIENT_BUFFER;
1107 size_t toCopy = strlen(cardName) + 1;
1108 memcpy(output, cardName, toCopy);
1114 return SCARD_S_SUCCESS;
1117static LONG WINAPI PCSC_SCardListCardsW(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, LPCBYTE pbAtr,
1118 LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount,
1119 WCHAR* mszCards, LPDWORD pcchCards)
1121 const char* cardName =
nullptr;
1122 DWORD outputLen = 1;
1123 WCHAR* output =
nullptr;
1124 BOOL autoAllocate = 0;
1126 if (!pbAtr || rgquidInterfaces || cguidInterfaceCount)
1127 return SCARD_E_UNSUPPORTED_FEATURE;
1130 return SCARD_E_INVALID_PARAMETER;
1132 autoAllocate = (*pcchCards == SCARD_AUTOALLOCATE);
1134 cardName = findCardByAtr(pbAtr);
1136 outputLen += strlen(cardName) + 1;
1138 *pcchCards = outputLen;
1141 output = calloc(outputLen,
sizeof(WCHAR));
1143 return SCARD_E_NO_MEMORY;
1145 *((LPWSTR*)mszCards) = output;
1150 return SCARD_S_SUCCESS;
1152 if (*pcchCards < outputLen)
1153 return SCARD_E_INSUFFICIENT_BUFFER;
1160 size_t toCopy = strlen(cardName) + 1;
1161 if (ConvertUtf8ToWChar(cardName, output, toCopy) < 0)
1162 return SCARD_F_INTERNAL_ERROR;
1168 return SCARD_S_SUCCESS;
1172PCSC_SCardListInterfacesA(SCARDCONTEXT hContext, LPCSTR szCard, LPGUID pguidInterfaces,
1173 LPDWORD pcguidInterfaces )
1175 WINPR_UNUSED(hContext);
1176 WINPR_UNUSED(szCard);
1177 WINPR_UNUSED(pguidInterfaces);
1178 WINPR_UNUSED(pcguidInterfaces);
1179 return SCARD_E_UNSUPPORTED_FEATURE;
1183PCSC_SCardListInterfacesW(SCARDCONTEXT hContext, LPCWSTR szCard, LPGUID pguidInterfaces,
1184 LPDWORD pcguidInterfaces )
1186 WINPR_UNUSED(hContext);
1187 WINPR_UNUSED(szCard);
1188 WINPR_UNUSED(pguidInterfaces);
1189 WINPR_UNUSED(pcguidInterfaces);
1190 return SCARD_E_UNSUPPORTED_FEATURE;
1193static LONG WINAPI PCSC_SCardGetProviderIdA(SCARDCONTEXT hContext, LPCSTR szCard,
1194 LPGUID pguidProviderId)
1196 WINPR_UNUSED(hContext);
1197 WINPR_UNUSED(szCard);
1198 WINPR_UNUSED(pguidProviderId);
1199 return SCARD_E_UNSUPPORTED_FEATURE;
1202static LONG WINAPI PCSC_SCardGetProviderIdW(SCARDCONTEXT hContext, LPCWSTR szCard,
1203 LPGUID pguidProviderId)
1205 WINPR_UNUSED(hContext);
1206 WINPR_UNUSED(szCard);
1207 WINPR_UNUSED(pguidProviderId);
1208 return SCARD_E_UNSUPPORTED_FEATURE;
1211static LONG WINAPI PCSC_SCardGetCardTypeProviderNameA(
1212 SCARDCONTEXT hContext, LPCSTR szCardName, DWORD dwProviderId,
1214 LPDWORD pcchProvider )
1216 WINPR_UNUSED(hContext);
1217 WINPR_UNUSED(szCardName);
1218 WINPR_UNUSED(dwProviderId);
1219 WINPR_UNUSED(szProvider);
1220 WINPR_UNUSED(pcchProvider);
1221 return SCARD_E_UNSUPPORTED_FEATURE;
1224static LONG WINAPI PCSC_SCardGetCardTypeProviderNameW(
1225 SCARDCONTEXT hContext, LPCWSTR szCardName, DWORD dwProviderId,
1227 LPDWORD pcchProvider )
1229 WINPR_UNUSED(hContext);
1230 WINPR_UNUSED(szCardName);
1231 WINPR_UNUSED(dwProviderId);
1232 WINPR_UNUSED(szProvider);
1233 WINPR_UNUSED(pcchProvider);
1234 return SCARD_E_UNSUPPORTED_FEATURE;
1237static LONG WINAPI PCSC_SCardIntroduceReaderGroupA(SCARDCONTEXT hContext, LPCSTR szGroupName)
1239 WINPR_UNUSED(hContext);
1240 WINPR_UNUSED(szGroupName);
1241 return SCARD_E_UNSUPPORTED_FEATURE;
1244static LONG WINAPI PCSC_SCardIntroduceReaderGroupW(SCARDCONTEXT hContext, LPCWSTR szGroupName)
1246 WINPR_UNUSED(hContext);
1247 WINPR_UNUSED(szGroupName);
1248 return SCARD_E_UNSUPPORTED_FEATURE;
1251static LONG WINAPI PCSC_SCardForgetReaderGroupA(SCARDCONTEXT hContext, LPCSTR szGroupName)
1253 WINPR_UNUSED(hContext);
1254 WINPR_UNUSED(szGroupName);
1255 return SCARD_E_UNSUPPORTED_FEATURE;
1258static LONG WINAPI PCSC_SCardForgetReaderGroupW(SCARDCONTEXT hContext, LPCWSTR szGroupName)
1260 WINPR_UNUSED(hContext);
1261 WINPR_UNUSED(szGroupName);
1262 return SCARD_E_UNSUPPORTED_FEATURE;
1265static LONG WINAPI PCSC_SCardIntroduceReaderA(SCARDCONTEXT hContext, LPCSTR szReaderName,
1266 LPCSTR szDeviceName)
1268 WINPR_UNUSED(hContext);
1269 WINPR_UNUSED(szReaderName);
1270 WINPR_UNUSED(szDeviceName);
1271 return SCARD_E_UNSUPPORTED_FEATURE;
1274static LONG WINAPI PCSC_SCardIntroduceReaderW(SCARDCONTEXT hContext, LPCWSTR szReaderName,
1275 LPCWSTR szDeviceName)
1277 WINPR_UNUSED(hContext);
1278 WINPR_UNUSED(szReaderName);
1279 WINPR_UNUSED(szDeviceName);
1280 return SCARD_E_UNSUPPORTED_FEATURE;
1283static LONG WINAPI PCSC_SCardForgetReaderA(SCARDCONTEXT hContext, LPCSTR szReaderName)
1285 WINPR_UNUSED(hContext);
1286 WINPR_UNUSED(szReaderName);
1287 return SCARD_E_UNSUPPORTED_FEATURE;
1290static LONG WINAPI PCSC_SCardForgetReaderW(SCARDCONTEXT hContext, LPCWSTR szReaderName)
1292 WINPR_UNUSED(hContext);
1293 WINPR_UNUSED(szReaderName);
1294 return SCARD_E_UNSUPPORTED_FEATURE;
1297static LONG WINAPI PCSC_SCardAddReaderToGroupA(SCARDCONTEXT hContext, LPCSTR szReaderName,
1300 WINPR_UNUSED(hContext);
1301 WINPR_UNUSED(szReaderName);
1302 WINPR_UNUSED(szGroupName);
1303 return SCARD_E_UNSUPPORTED_FEATURE;
1306static LONG WINAPI PCSC_SCardAddReaderToGroupW(SCARDCONTEXT hContext, LPCWSTR szReaderName,
1307 LPCWSTR szGroupName)
1309 WINPR_UNUSED(hContext);
1310 WINPR_UNUSED(szReaderName);
1311 WINPR_UNUSED(szGroupName);
1312 return SCARD_E_UNSUPPORTED_FEATURE;
1315static LONG WINAPI PCSC_SCardRemoveReaderFromGroupA(SCARDCONTEXT hContext, LPCSTR szReaderName,
1318 WINPR_UNUSED(hContext);
1319 WINPR_UNUSED(szReaderName);
1320 WINPR_UNUSED(szGroupName);
1321 return SCARD_E_UNSUPPORTED_FEATURE;
1324static LONG WINAPI PCSC_SCardRemoveReaderFromGroupW(SCARDCONTEXT hContext, LPCWSTR szReaderName,
1325 LPCWSTR szGroupName)
1327 WINPR_UNUSED(hContext);
1328 WINPR_UNUSED(szReaderName);
1329 WINPR_UNUSED(szGroupName);
1330 return SCARD_E_UNSUPPORTED_FEATURE;
1333static LONG WINAPI PCSC_SCardIntroduceCardTypeA(SCARDCONTEXT hContext, LPCSTR szCardName,
1334 LPCGUID pguidPrimaryProvider,
1335 LPCGUID rgguidInterfaces, DWORD dwInterfaceCount,
1336 LPCBYTE pbAtr, LPCBYTE pbAtrMask, DWORD cbAtrLen)
1338 WINPR_UNUSED(hContext);
1339 WINPR_UNUSED(szCardName);
1340 WINPR_UNUSED(pguidPrimaryProvider);
1341 WINPR_UNUSED(rgguidInterfaces);
1342 WINPR_UNUSED(dwInterfaceCount);
1343 WINPR_UNUSED(pbAtr);
1344 WINPR_UNUSED(pbAtrMask);
1345 WINPR_UNUSED(cbAtrLen);
1346 return SCARD_E_UNSUPPORTED_FEATURE;
1349static LONG WINAPI PCSC_SCardIntroduceCardTypeW(SCARDCONTEXT hContext, LPCWSTR szCardName,
1350 LPCGUID pguidPrimaryProvider,
1351 LPCGUID rgguidInterfaces, DWORD dwInterfaceCount,
1352 LPCBYTE pbAtr, LPCBYTE pbAtrMask, DWORD cbAtrLen)
1354 WINPR_UNUSED(hContext);
1355 WINPR_UNUSED(szCardName);
1356 WINPR_UNUSED(pguidPrimaryProvider);
1357 WINPR_UNUSED(rgguidInterfaces);
1358 WINPR_UNUSED(dwInterfaceCount);
1359 WINPR_UNUSED(pbAtr);
1360 WINPR_UNUSED(pbAtrMask);
1361 WINPR_UNUSED(cbAtrLen);
1362 return SCARD_E_UNSUPPORTED_FEATURE;
1365static LONG WINAPI PCSC_SCardSetCardTypeProviderNameA(SCARDCONTEXT hContext, LPCSTR szCardName,
1366 DWORD dwProviderId, LPCSTR szProvider)
1368 WINPR_UNUSED(hContext);
1369 WINPR_UNUSED(szCardName);
1370 WINPR_UNUSED(dwProviderId);
1371 WINPR_UNUSED(szProvider);
1372 return SCARD_E_UNSUPPORTED_FEATURE;
1375static LONG WINAPI PCSC_SCardSetCardTypeProviderNameW(SCARDCONTEXT hContext, LPCWSTR szCardName,
1376 DWORD dwProviderId, LPCWSTR szProvider)
1378 WINPR_UNUSED(hContext);
1379 WINPR_UNUSED(szCardName);
1380 WINPR_UNUSED(dwProviderId);
1381 WINPR_UNUSED(szProvider);
1382 return SCARD_E_UNSUPPORTED_FEATURE;
1385static LONG WINAPI PCSC_SCardForgetCardTypeA(SCARDCONTEXT hContext, LPCSTR szCardName)
1387 WINPR_UNUSED(hContext);
1388 WINPR_UNUSED(szCardName);
1389 return SCARD_E_UNSUPPORTED_FEATURE;
1392static LONG WINAPI PCSC_SCardForgetCardTypeW(SCARDCONTEXT hContext, LPCWSTR szCardName)
1394 WINPR_UNUSED(hContext);
1395 WINPR_UNUSED(szCardName);
1396 return SCARD_E_UNSUPPORTED_FEATURE;
1399static LONG WINAPI PCSC_SCardFreeMemory_Internal(SCARDCONTEXT hContext, LPVOID pvMem)
1401 PCSC_LONG status = SCARD_S_SUCCESS;
1403 if (PCSC_RemoveMemoryBlock(hContext, pvMem))
1406 status = SCARD_S_SUCCESS;
1410 if (g_PCSC.pfnSCardFreeMemory)
1412 status = g_PCSC.pfnSCardFreeMemory(hContext, pvMem);
1416 return PCSC_MapErrorCodeToWinSCard(status);
1419static LONG WINAPI PCSC_SCardFreeMemory(SCARDCONTEXT hContext, LPVOID pvMem)
1421 LONG status = SCARD_S_SUCCESS;
1425 if (!PCSC_LockCardContext(hContext))
1426 return SCARD_E_INVALID_HANDLE;
1429 status = PCSC_SCardFreeMemory_Internal(hContext, pvMem);
1433 if (!PCSC_UnlockCardContext(hContext))
1434 return SCARD_E_INVALID_HANDLE;
1440static HANDLE WINAPI PCSC_SCardAccessStartedEvent(
void)
1443 SCARDCONTEXT hContext = 0;
1445 status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM,
nullptr,
nullptr, &hContext);
1447 if (status != SCARD_S_SUCCESS)
1450 status = PCSC_SCardReleaseContext(hContext);
1452 if (status != SCARD_S_SUCCESS)
1455 if (!g_StartedEvent)
1457 if (!(g_StartedEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
1460 if (!SetEvent(g_StartedEvent))
1462 (void)CloseHandle(g_StartedEvent);
1467 g_StartedEventRefCount++;
1468 return g_StartedEvent;
1471static void WINAPI PCSC_SCardReleaseStartedEvent(
void)
1473 g_StartedEventRefCount--;
1475 if (g_StartedEventRefCount == 0)
1479 (void)CloseHandle(g_StartedEvent);
1480 g_StartedEvent =
nullptr;
1485static LONG WINAPI PCSC_SCardLocateCardsA(SCARDCONTEXT hContext, LPCSTR mszCards,
1488 WINPR_UNUSED(hContext);
1489 WINPR_UNUSED(mszCards);
1490 WINPR_UNUSED(rgReaderStates);
1491 WINPR_UNUSED(cReaders);
1492 return SCARD_E_UNSUPPORTED_FEATURE;
1495static LONG WINAPI PCSC_SCardLocateCardsW(SCARDCONTEXT hContext, LPCWSTR mszCards,
1498 WINPR_UNUSED(hContext);
1499 WINPR_UNUSED(mszCards);
1500 WINPR_UNUSED(rgReaderStates);
1501 WINPR_UNUSED(cReaders);
1502 return SCARD_E_UNSUPPORTED_FEATURE;
1505static LONG WINAPI PCSC_SCardLocateCardsByATRA(SCARDCONTEXT hContext,
LPSCARD_ATRMASK rgAtrMasks,
1509 WINPR_UNUSED(hContext);
1510 WINPR_UNUSED(rgAtrMasks);
1511 WINPR_UNUSED(cAtrs);
1512 WINPR_UNUSED(rgReaderStates);
1513 WINPR_UNUSED(cReaders);
1514 return SCARD_E_UNSUPPORTED_FEATURE;
1517static LONG WINAPI PCSC_SCardLocateCardsByATRW(SCARDCONTEXT hContext,
LPSCARD_ATRMASK rgAtrMasks,
1521 WINPR_UNUSED(hContext);
1522 WINPR_UNUSED(rgAtrMasks);
1523 WINPR_UNUSED(cAtrs);
1524 WINPR_UNUSED(rgReaderStates);
1525 WINPR_UNUSED(cReaders);
1526 return SCARD_E_UNSUPPORTED_FEATURE;
1529static LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext, DWORD dwTimeout,
1533 INT64* map =
nullptr;
1534 PCSC_DWORD cMappedReaders = 0;
1536 PCSC_LONG status = SCARD_S_SUCCESS;
1537 PCSC_DWORD pcsc_dwTimeout = (PCSC_DWORD)dwTimeout;
1538 PCSC_DWORD pcsc_cReaders = (PCSC_DWORD)cReaders;
1540 if (!g_PCSC.pfnSCardGetStatusChange)
1541 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardGetStatusChange");
1544 return SCARD_S_SUCCESS;
1547 pcsc_dwTimeout = pcsc_dwTimeout ? pcsc_dwTimeout : 1;
1561 map = (INT64*)calloc(pcsc_cReaders,
sizeof(INT64));
1564 return SCARD_E_NO_MEMORY;
1571 return SCARD_E_NO_MEMORY;
1575 for (PCSC_DWORD i = 0; i < pcsc_cReaders; i++)
1577 if (!g_PnP_Notification)
1580 if (!reader->szReader)
1582 if (0 == _stricmp(reader->szReader, SMARTCARD_PNP_NOTIFICATION_A))
1590 states[j].szReader = rgReaderStates[i].szReader;
1591 states[j].dwCurrentState = rgReaderStates[i].dwCurrentState;
1592 states[j].pvUserData = rgReaderStates[i].pvUserData;
1593 states[j].dwEventState = rgReaderStates[i].dwEventState;
1594 states[j].cbAtr = rgReaderStates[i].cbAtr;
1595 CopyMemory(&(states[j].rgbAtr), &(rgReaderStates[i].rgbAtr), PCSC_MAX_ATR_SIZE);
1601 if (cMappedReaders > 0)
1603 status = g_PCSC.pfnSCardGetStatusChange(hContext, pcsc_dwTimeout, states, cMappedReaders);
1607 status = SCARD_S_SUCCESS;
1610 for (PCSC_DWORD i = 0; i < pcsc_cReaders; i++)
1615 PCSC_DWORD k = (PCSC_DWORD)map[i];
1616 rgReaderStates[i].dwCurrentState = (DWORD)states[k].dwCurrentState;
1617 rgReaderStates[i].cbAtr = (DWORD)states[k].cbAtr;
1618 CopyMemory(&(rgReaderStates[i].rgbAtr), &(states[k].rgbAtr), PCSC_MAX_ATR_SIZE);
1619 rgReaderStates[i].dwEventState = (DWORD)states[k].dwEventState;
1624 return PCSC_MapErrorCodeToWinSCard(status);
1627static LONG WINAPI PCSC_SCardGetStatusChangeA(SCARDCONTEXT hContext, DWORD dwTimeout,
1630 LONG status = SCARD_S_SUCCESS;
1632 if (!PCSC_LockCardContext(hContext))
1633 return SCARD_E_INVALID_HANDLE;
1635 status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, rgReaderStates, cReaders);
1637 if (!PCSC_UnlockCardContext(hContext))
1638 return SCARD_E_INVALID_HANDLE;
1643static LONG WINAPI PCSC_SCardGetStatusChangeW(SCARDCONTEXT hContext, DWORD dwTimeout,
1647 LONG status = SCARD_S_SUCCESS;
1649 if (!g_PCSC.pfnSCardGetStatusChange)
1650 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardGetStatusChange");
1652 if (!PCSC_LockCardContext(hContext))
1653 return SCARD_E_INVALID_HANDLE;
1659 (void)PCSC_UnlockCardContext(hContext);
1660 return SCARD_E_NO_MEMORY;
1663 for (DWORD index = 0; index < cReaders; index++)
1668 cur->szReader = ConvertWCharToUtf8Alloc(curReader->szReader,
nullptr);
1669 cur->pvUserData = curReader->pvUserData;
1670 cur->dwCurrentState = curReader->dwCurrentState;
1671 cur->dwEventState = curReader->dwEventState;
1672 cur->cbAtr = curReader->cbAtr;
1673 CopyMemory(&(cur->rgbAtr), &(curReader->rgbAtr), ARRAYSIZE(cur->rgbAtr));
1676 status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, states, cReaders);
1678 for (DWORD index = 0; index < cReaders; index++)
1680 free((
void*)states[index].szReader);
1681 rgReaderStates[index].pvUserData = states[index].pvUserData;
1682 rgReaderStates[index].dwCurrentState = states[index].dwCurrentState;
1683 rgReaderStates[index].dwEventState = states[index].dwEventState;
1684 rgReaderStates[index].cbAtr = states[index].cbAtr;
1685 CopyMemory(&(rgReaderStates[index].rgbAtr), &(states[index].rgbAtr), 36);
1690 if (!PCSC_UnlockCardContext(hContext))
1691 return SCARD_E_INVALID_HANDLE;
1696static LONG WINAPI PCSC_SCardCancel(SCARDCONTEXT hContext)
1698 PCSC_LONG status = SCARD_S_SUCCESS;
1700 if (!g_PCSC.pfnSCardCancel)
1701 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardCancel");
1703 status = g_PCSC.pfnSCardCancel(hContext);
1704 return PCSC_MapErrorCodeToWinSCard(status);
1707static LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext, LPCSTR szReader,
1708 DWORD dwShareMode, DWORD dwPreferredProtocols,
1709 LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
1712 const char* szReaderPCSC =
nullptr;
1713 PCSC_LONG status = SCARD_S_SUCCESS;
1714 PCSC_SCARDHANDLE* pCard =
nullptr;
1715 PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD)dwShareMode;
1716 PCSC_DWORD pcsc_dwPreferredProtocols = 0;
1717 PCSC_DWORD pcsc_dwActiveProtocol = 0;
1719 if (!g_PCSC.pfnSCardConnect)
1720 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardConnect");
1722 shared = (dwShareMode == SCARD_SHARE_DIRECT) != 0;
1723 PCSC_WaitForCardAccess(hContext, 0, shared);
1724 szReaderPCSC = szReader;
1733 if (pcsc_dwShareMode == SCARD_SHARE_DIRECT && dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED)
1734 pcsc_dwPreferredProtocols = SCARD_PROTOCOL_UNDEFINED;
1736 pcsc_dwPreferredProtocols =
1737 (PCSC_DWORD)PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
1739 status = g_PCSC.pfnSCardConnect(hContext, szReaderPCSC, pcsc_dwShareMode,
1740 pcsc_dwPreferredProtocols, phCard, &pcsc_dwActiveProtocol);
1742 if (status == SCARD_S_SUCCESS)
1744 pCard = PCSC_ConnectCardHandle(hContext, *phCard);
1745 *pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD)pcsc_dwActiveProtocol);
1746 pCard->shared = shared;
1749 PCSC_WaitForCardAccess(hContext, pCard->hSharedContext, shared);
1752 return PCSC_MapErrorCodeToWinSCard(status);
1755static LONG WINAPI PCSC_SCardConnectA(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode,
1756 DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
1757 LPDWORD pdwActiveProtocol)
1759 LONG status = SCARD_S_SUCCESS;
1761 if (!PCSC_LockCardContext(hContext))
1762 return SCARD_E_INVALID_HANDLE;
1764 status = PCSC_SCardConnect_Internal(hContext, szReader, dwShareMode, dwPreferredProtocols,
1765 phCard, pdwActiveProtocol);
1767 if (!PCSC_UnlockCardContext(hContext))
1768 return SCARD_E_INVALID_HANDLE;
1773static LONG WINAPI PCSC_SCardConnectW(SCARDCONTEXT hContext, LPCWSTR szReader, DWORD dwShareMode,
1774 DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
1775 LPDWORD pdwActiveProtocol)
1777 LPSTR szReaderA =
nullptr;
1778 LONG status = SCARD_S_SUCCESS;
1780 if (!PCSC_LockCardContext(hContext))
1781 return SCARD_E_INVALID_HANDLE;
1785 szReaderA = ConvertWCharToUtf8Alloc(szReader,
nullptr);
1787 return SCARD_E_INSUFFICIENT_BUFFER;
1790 status = PCSC_SCardConnect_Internal(hContext, szReaderA, dwShareMode, dwPreferredProtocols,
1791 phCard, pdwActiveProtocol);
1794 if (!PCSC_UnlockCardContext(hContext))
1795 return SCARD_E_INVALID_HANDLE;
1800static LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
1801 DWORD dwPreferredProtocols, DWORD dwInitialization,
1802 LPDWORD pdwActiveProtocol)
1805 PCSC_LONG status = SCARD_S_SUCCESS;
1806 PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD)dwShareMode;
1807 PCSC_DWORD pcsc_dwPreferredProtocols = 0;
1808 PCSC_DWORD pcsc_dwInitialization = (PCSC_DWORD)dwInitialization;
1809 PCSC_DWORD pcsc_dwActiveProtocol = 0;
1811 if (!g_PCSC.pfnSCardReconnect)
1812 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardReconnect");
1814 shared = (dwShareMode == SCARD_SHARE_DIRECT) != 0;
1815 PCSC_WaitForCardAccess(0, hCard, shared);
1816 pcsc_dwPreferredProtocols = (PCSC_DWORD)PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
1817 status = g_PCSC.pfnSCardReconnect(hCard, pcsc_dwShareMode, pcsc_dwPreferredProtocols,
1818 pcsc_dwInitialization, &pcsc_dwActiveProtocol);
1820 *pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD)pcsc_dwActiveProtocol);
1821 return PCSC_MapErrorCodeToWinSCard(status);
1824static LONG WINAPI PCSC_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
1826 PCSC_LONG status = SCARD_S_SUCCESS;
1827 PCSC_DWORD pcsc_dwDisposition = (PCSC_DWORD)dwDisposition;
1829 if (!g_PCSC.pfnSCardDisconnect)
1830 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardDisconnect");
1832 status = g_PCSC.pfnSCardDisconnect(hCard, pcsc_dwDisposition);
1834 if (status == SCARD_S_SUCCESS)
1836 PCSC_DisconnectCardHandle(hCard);
1839 PCSC_ReleaseCardAccess(0, hCard);
1840 return PCSC_MapErrorCodeToWinSCard(status);
1843static LONG WINAPI PCSC_SCardBeginTransaction(SCARDHANDLE hCard)
1845 PCSC_LONG status = SCARD_S_SUCCESS;
1846 PCSC_SCARDHANDLE* pCard =
nullptr;
1847 PCSC_SCARDCONTEXT* pContext =
nullptr;
1849 if (!g_PCSC.pfnSCardBeginTransaction)
1850 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardBeginTransaction");
1852 pCard = PCSC_GetCardHandleData(hCard);
1855 return SCARD_E_INVALID_HANDLE;
1857 pContext = PCSC_GetCardContextData(pCard->hSharedContext);
1860 return SCARD_E_INVALID_HANDLE;
1862 if (pContext->isTransactionLocked)
1863 return SCARD_S_SUCCESS;
1865 status = g_PCSC.pfnSCardBeginTransaction(hCard);
1867 pContext->isTransactionLocked = TRUE;
1868 return PCSC_MapErrorCodeToWinSCard(status);
1871static LONG WINAPI PCSC_SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
1873 PCSC_LONG status = SCARD_S_SUCCESS;
1874 PCSC_SCARDHANDLE* pCard =
nullptr;
1875 PCSC_SCARDCONTEXT* pContext =
nullptr;
1876 PCSC_DWORD pcsc_dwDisposition = (PCSC_DWORD)dwDisposition;
1878 if (!g_PCSC.pfnSCardEndTransaction)
1879 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardEndTransaction");
1881 pCard = PCSC_GetCardHandleData(hCard);
1884 return SCARD_E_INVALID_HANDLE;
1886 pContext = PCSC_GetCardContextData(pCard->hSharedContext);
1889 return SCARD_E_INVALID_HANDLE;
1891 PCSC_ReleaseCardAccess(0, hCard);
1893 if (!pContext->isTransactionLocked)
1894 return SCARD_S_SUCCESS;
1896 status = g_PCSC.pfnSCardEndTransaction(hCard, pcsc_dwDisposition);
1898 pContext->isTransactionLocked = FALSE;
1899 return PCSC_MapErrorCodeToWinSCard(status);
1902static LONG WINAPI PCSC_SCardCancelTransaction(SCARDHANDLE hCard)
1904 WINPR_UNUSED(hCard);
1905 return SCARD_S_SUCCESS;
1912static LONG WINAPI PCSC_SCardStatus_Internal(SCARDHANDLE hCard, LPSTR mszReaderNames,
1913 LPDWORD pcchReaderLen, LPDWORD pdwState,
1914 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen,
1917 PCSC_SCARDHANDLE* pCard =
nullptr;
1918 SCARDCONTEXT hContext = 0;
1919 PCSC_LONG status = 0;
1920 PCSC_DWORD pcsc_cchReaderLen = 0;
1921 PCSC_DWORD pcsc_cbAtrLen = 0;
1922 PCSC_DWORD pcsc_dwState = 0;
1923 PCSC_DWORD pcsc_dwProtocol = 0;
1924 BOOL allocateReader = FALSE;
1925 BOOL allocateAtr = FALSE;
1926 LPSTR readerNames = mszReaderNames;
1928 LPSTR tReader =
nullptr;
1929 LPBYTE tATR =
nullptr;
1931 if (!g_PCSC.pfnSCardStatus)
1932 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardStatus");
1934 pCard = PCSC_GetCardHandleData(hCard);
1937 return SCARD_E_INVALID_VALUE;
1939 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
1940 hContext = PCSC_GetCardContextFromHandle(hCard);
1943 return SCARD_E_INVALID_VALUE;
1945 status = g_PCSC.pfnSCardStatus(hCard,
nullptr, &pcsc_cchReaderLen,
nullptr,
nullptr,
nullptr,
1948 if (status != STATUS_SUCCESS)
1949 return PCSC_MapErrorCodeToWinSCard(status);
1951 pcsc_cchReaderLen++;
1954 pcsc_cchReaderLen *= 2;
1958 if (*pcchReaderLen == SCARD_AUTOALLOCATE)
1959 allocateReader = TRUE;
1960 else if (mszReaderNames && (*pcchReaderLen < pcsc_cchReaderLen))
1961 return SCARD_E_INSUFFICIENT_BUFFER;
1963 pcsc_cchReaderLen = *pcchReaderLen;
1968 if (*pcbAtrLen == SCARD_AUTOALLOCATE)
1970 else if (pbAtr && (*pcbAtrLen < pcsc_cbAtrLen))
1971 return SCARD_E_INSUFFICIENT_BUFFER;
1973 pcsc_cbAtrLen = *pcbAtrLen;
1976 if (allocateReader && pcsc_cchReaderLen > 0 && mszReaderNames)
1983 if (OSXVersion == 0x10100000)
1984 pcsc_cchReaderLen++;
1987 tReader = calloc(
sizeof(CHAR), pcsc_cchReaderLen + 1);
1991 status = ERROR_NOT_ENOUGH_MEMORY;
1995 readerNames = tReader;
1998 if (allocateAtr && pcsc_cbAtrLen > 0 && pbAtr)
2000 tATR = calloc(1, pcsc_cbAtrLen);
2004 status = ERROR_NOT_ENOUGH_MEMORY;
2011 status = g_PCSC.pfnSCardStatus(hCard, readerNames, &pcsc_cchReaderLen, &pcsc_dwState,
2012 &pcsc_dwProtocol, atr, &pcsc_cbAtrLen);
2014 if (status != STATUS_SUCCESS)
2019 PCSC_AddMemoryBlock(hContext, tATR);
2020 *(BYTE**)pbAtr = tATR;
2028 WCHAR* tmp = ConvertMszUtf8NToWCharAlloc(tReader, pcsc_cchReaderLen + 1, &size);
2032 status = ERROR_NOT_ENOUGH_MEMORY;
2038 PCSC_AddMemoryBlock(hContext, tmp);
2039 *(WCHAR**)mszReaderNames = tmp;
2043 tReader[pcsc_cchReaderLen - 1] =
'\0';
2044 PCSC_AddMemoryBlock(hContext, tReader);
2045 *(
char**)mszReaderNames = tReader;
2049 pcsc_dwState &= 0xFFFF;
2052 *pdwState = PCSC_ConvertCardStateToWinSCard((DWORD)pcsc_dwState, status);
2055 *pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD)pcsc_dwProtocol);
2058 *pcbAtrLen = (DWORD)pcsc_cbAtrLen;
2062 WINPR_ASSERT(pcsc_cchReaderLen < UINT32_MAX);
2063 *pcchReaderLen = (DWORD)pcsc_cchReaderLen + 1u;
2066 return (LONG)status;
2070 return (LONG)status;
2073static LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard, LPDWORD pdwState, LPDWORD pdwProtocol,
2074 LPBYTE pbAtr, LPDWORD pcbAtrLen)
2076 DWORD cchReaderLen = 0;
2077 SCARDCONTEXT hContext = 0;
2078 LPSTR mszReaderNames =
nullptr;
2079 PCSC_LONG status = SCARD_S_SUCCESS;
2080 PCSC_SCARDHANDLE* pCard =
nullptr;
2081 DWORD pcsc_dwState = 0;
2082 DWORD pcsc_dwProtocol = 0;
2083 DWORD pcsc_cbAtrLen = 0;
2086 pcsc_cbAtrLen = (DWORD)*pcbAtrLen;
2088 if (!g_PCSC.pfnSCardStatus)
2089 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardStatus");
2091 pCard = PCSC_GetCardHandleData(hCard);
2094 return SCARD_E_INVALID_VALUE;
2096 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2097 hContext = PCSC_GetCardContextFromHandle(hCard);
2100 return SCARD_E_INVALID_VALUE;
2102 cchReaderLen = SCARD_AUTOALLOCATE;
2103 status = PCSC_SCardStatus_Internal(hCard, (LPSTR)&mszReaderNames, &cchReaderLen, &pcsc_dwState,
2104 &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen, FALSE);
2107 PCSC_SCardFreeMemory_Internal(hContext, mszReaderNames);
2109 *pdwState = pcsc_dwState;
2110 *pdwProtocol = PCSC_ConvertProtocolsToWinSCard(pcsc_dwProtocol);
2112 *pcbAtrLen = pcsc_cbAtrLen;
2113 return PCSC_MapErrorCodeToWinSCard(status);
2116static LONG WINAPI PCSC_SCardStatusA(SCARDHANDLE hCard, LPSTR mszReaderNames, LPDWORD pcchReaderLen,
2117 LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr,
2121 return PCSC_SCardStatus_Internal(hCard, mszReaderNames, pcchReaderLen, pdwState, pdwProtocol,
2122 pbAtr, pcbAtrLen, FALSE);
2125static LONG WINAPI PCSC_SCardStatusW(SCARDHANDLE hCard, LPWSTR mszReaderNames,
2126 LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol,
2127 LPBYTE pbAtr, LPDWORD pcbAtrLen)
2130 return PCSC_SCardStatus_Internal(hCard, (LPSTR)mszReaderNames, pcchReaderLen, pdwState,
2131 pdwProtocol, pbAtr, pcbAtrLen, TRUE);
2135 LPCBYTE pbSendBuffer, DWORD cbSendLength,
2137 LPDWORD pcbRecvLength)
2139 PCSC_LONG status = SCARD_S_SUCCESS;
2140 PCSC_SCARDHANDLE* pCard =
nullptr;
2141 PCSC_DWORD cbExtraBytes = 0;
2142 BYTE* pbExtraBytes =
nullptr;
2143 BYTE* pcsc_pbExtraBytes =
nullptr;
2144 PCSC_DWORD pcsc_cbSendLength = (PCSC_DWORD)cbSendLength;
2145 PCSC_DWORD pcsc_cbRecvLength = 0;
2153 } sendPci, recvPci, inRecvPci, inSendPci;
2155 sendPci.ps =
nullptr;
2156 recvPci.ps =
nullptr;
2157 inRecvPci.lps = pioRecvPci;
2158 inSendPci.lpcs = pioSendPci;
2160 if (!g_PCSC.pfnSCardTransmit)
2161 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardTransmit");
2163 pCard = PCSC_GetCardHandleData(hCard);
2166 return SCARD_E_INVALID_VALUE;
2168 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2171 return SCARD_E_INVALID_PARAMETER;
2173 if (*pcbRecvLength == SCARD_AUTOALLOCATE)
2174 return SCARD_E_INVALID_PARAMETER;
2176 pcsc_cbRecvLength = (PCSC_DWORD)*pcbRecvLength;
2178 if (!inSendPci.lpcs)
2180 PCSC_DWORD dwState = 0;
2181 PCSC_DWORD cbAtrLen = 0;
2182 PCSC_DWORD dwProtocol = 0;
2183 PCSC_DWORD cchReaderLen = 0;
2188 status = g_PCSC.pfnSCardStatus(hCard,
nullptr, &cchReaderLen, &dwState, &dwProtocol,
2189 nullptr, &cbAtrLen);
2191 if (status == SCARD_S_SUCCESS)
2193 if (dwProtocol == SCARD_PROTOCOL_T0)
2194 sendPci.pcs = PCSC_SCARD_PCI_T0;
2195 else if (dwProtocol == SCARD_PROTOCOL_T1)
2196 sendPci.pcs = PCSC_SCARD_PCI_T1;
2197 else if (dwProtocol == PCSC_SCARD_PROTOCOL_RAW)
2198 sendPci.pcs = PCSC_SCARD_PCI_RAW;
2207 return SCARD_E_NO_MEMORY;
2209 sendPci.ps->dwProtocol = (PCSC_DWORD)inSendPci.lpcs->dwProtocol;
2213 CopyMemory(pcsc_pbExtraBytes, pbExtraBytes, cbExtraBytes);
2226 return SCARD_E_NO_MEMORY;
2229 recvPci.ps->dwProtocol = (PCSC_DWORD)inRecvPci.lps->dwProtocol;
2233 CopyMemory(pcsc_pbExtraBytes, pbExtraBytes, cbExtraBytes);
2236 status = g_PCSC.pfnSCardTransmit(hCard, sendPci.ps, pbSendBuffer, pcsc_cbSendLength, recvPci.ps,
2237 pbRecvBuffer, &pcsc_cbRecvLength);
2239 *pcbRecvLength = (DWORD)pcsc_cbRecvLength;
2250 CopyMemory(pbExtraBytes, pcsc_pbExtraBytes, cbExtraBytes);
2255 return PCSC_MapErrorCodeToWinSCard(status);
2259static LONG WINAPI PCSC_SCardGetTransmitCount(SCARDHANDLE hCard, LPDWORD pcTransmitCount)
2261 WINPR_UNUSED(pcTransmitCount);
2262 PCSC_SCARDHANDLE* pCard =
nullptr;
2264 pCard = PCSC_GetCardHandleData(hCard);
2267 return SCARD_E_INVALID_VALUE;
2269 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2270 return SCARD_S_SUCCESS;
2273static LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID lpInBuffer,
2274 DWORD cbInBufferSize, LPVOID lpOutBuffer,
2275 DWORD cbOutBufferSize, LPDWORD lpBytesReturned)
2277 DWORD IoCtlFunction = 0;
2278 DWORD IoCtlDeviceType = 0;
2279 BOOL getFeatureRequest = FALSE;
2280 PCSC_LONG status = SCARD_S_SUCCESS;
2281 PCSC_SCARDHANDLE* pCard =
nullptr;
2282 PCSC_DWORD pcsc_dwControlCode = 0;
2283 PCSC_DWORD pcsc_cbInBufferSize = (PCSC_DWORD)cbInBufferSize;
2284 PCSC_DWORD pcsc_cbOutBufferSize = (PCSC_DWORD)cbOutBufferSize;
2285 PCSC_DWORD pcsc_BytesReturned = 0;
2287 if (!g_PCSC.pfnSCardControl)
2288 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardControl");
2290 pCard = PCSC_GetCardHandleData(hCard);
2293 return SCARD_E_INVALID_VALUE;
2295 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2306 IoCtlFunction = FUNCTION_FROM_CTL_CODE(dwControlCode);
2307 IoCtlDeviceType = DEVICE_TYPE_FROM_CTL_CODE(dwControlCode);
2309 if (dwControlCode == IOCTL_SMARTCARD_GET_FEATURE_REQUEST)
2310 getFeatureRequest = TRUE;
2312 if (IoCtlDeviceType == FILE_DEVICE_SMARTCARD)
2313 dwControlCode = PCSC_SCARD_CTL_CODE(IoCtlFunction);
2315 pcsc_dwControlCode = (PCSC_DWORD)dwControlCode;
2316 status = g_PCSC.pfnSCardControl(hCard, pcsc_dwControlCode, lpInBuffer, pcsc_cbInBufferSize,
2317 lpOutBuffer, pcsc_cbOutBufferSize, &pcsc_BytesReturned);
2319 *lpBytesReturned = (DWORD)pcsc_BytesReturned;
2321 if (getFeatureRequest)
2327 return SCARD_E_UNEXPECTED;
2331 for (DWORD index = 0; index < count; index++)
2333 if (tlv[index].length != 4)
2334 return SCARD_E_UNEXPECTED;
2338 return PCSC_MapErrorCodeToWinSCard(status);
2341static LONG WINAPI PCSC_SCardGetAttrib_Internal(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
2344 SCARDCONTEXT hContext = 0;
2345 BOOL pcbAttrLenAlloc = FALSE;
2346 PCSC_LONG status = SCARD_S_SUCCESS;
2347 PCSC_SCARDHANDLE* pCard =
nullptr;
2348 PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD)dwAttrId;
2349 PCSC_DWORD pcsc_cbAttrLen = 0;
2351 if (!g_PCSC.pfnSCardGetAttrib)
2352 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardGetAttrib");
2354 pCard = PCSC_GetCardHandleData(hCard);
2357 return SCARD_E_INVALID_VALUE;
2359 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2360 hContext = PCSC_GetCardContextFromHandle(hCard);
2363 return SCARD_E_INVALID_HANDLE;
2366 return SCARD_E_INVALID_PARAMETER;
2368 if (*pcbAttrLen == SCARD_AUTOALLOCATE)
2371 return SCARD_E_INVALID_PARAMETER;
2372 pcbAttrLenAlloc = TRUE;
2375 pcsc_cbAttrLen = pcbAttrLenAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD)*pcbAttrLen;
2377 if (pcbAttrLenAlloc && !g_SCardAutoAllocate)
2380 status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId,
nullptr, &pcsc_cbAttrLen);
2382 if (status == SCARD_S_SUCCESS)
2384 BYTE* tmp = (BYTE*)calloc(1, pcsc_cbAttrLen);
2387 return SCARD_E_NO_MEMORY;
2389 status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, tmp, &pcsc_cbAttrLen);
2391 if (status != SCARD_S_SUCCESS)
2397 PCSC_AddMemoryBlock(hContext, tmp);
2398 *(BYTE**)pbAttr = tmp;
2403 status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, pbAttr, &pcsc_cbAttrLen);
2406 if (status == SCARD_S_SUCCESS)
2407 *pcbAttrLen = (DWORD)pcsc_cbAttrLen;
2408 return PCSC_MapErrorCodeToWinSCard(status);
2411static LONG WINAPI PCSC_SCardGetAttrib_FriendlyName(SCARDHANDLE hCard, DWORD dwAttrId,
2412 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2414 char* namePCSC =
nullptr;
2415 char* pbAttrA =
nullptr;
2417 SCARDCONTEXT hContext = PCSC_GetCardContextFromHandle(hCard);
2420 return SCARD_E_INVALID_HANDLE;
2423 return SCARD_E_INVALID_PARAMETER;
2424 const DWORD cbAttrLen = *pcbAttrLen;
2425 *pcbAttrLen = SCARD_AUTOALLOCATE;
2426 LONG status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A,
2427 (LPBYTE)&pbAttrA, pcbAttrLen);
2429 if (status != SCARD_S_SUCCESS)
2431 WCHAR* pbAttrW =
nullptr;
2433 *pcbAttrLen = SCARD_AUTOALLOCATE;
2434 status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W,
2435 (LPBYTE)&pbAttrW, pcbAttrLen);
2437 if (status != SCARD_S_SUCCESS)
2440 namePCSC = ConvertMszWCharNToUtf8Alloc(pbAttrW, *pcbAttrLen,
nullptr);
2441 PCSC_SCardFreeMemory_Internal(hContext, pbAttrW);
2445 namePCSC = strndup(pbAttrA, *pcbAttrLen);
2448 return SCARD_E_NO_MEMORY;
2450 PCSC_SCardFreeMemory_Internal(hContext, pbAttrA);
2453 size_t length = strnlen(namePCSC, *pcbAttrLen);
2455 if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W)
2458 WCHAR* friendlyNameW = ConvertUtf8NToWCharAlloc(namePCSC, length, &size);
2462 status = SCARD_E_NO_MEMORY;
2467 if (cbAttrLen == SCARD_AUTOALLOCATE)
2469 WINPR_ASSERT(length <= UINT32_MAX /
sizeof(WCHAR));
2470 *(WCHAR**)pbAttr = friendlyNameW;
2471 *pcbAttrLen = (UINT32)length *
sizeof(WCHAR);
2472 PCSC_AddMemoryBlock(hContext, friendlyNameW);
2476 const size_t wlen = length *
sizeof(WCHAR);
2477 *pcbAttrLen = WINPR_ASSERTING_INT_CAST(uint32_t, wlen);
2478 if ((wlen > cbAttrLen) && pbAttr)
2479 status = SCARD_E_INSUFFICIENT_BUFFER;
2481 CopyMemory(pbAttr, friendlyNameW, (length *
sizeof(WCHAR)));
2483 free(friendlyNameW);
2491 if (cbAttrLen == SCARD_AUTOALLOCATE)
2493 *(CHAR**)pbAttr = namePCSC;
2494 WINPR_ASSERT(length <= UINT32_MAX);
2495 *pcbAttrLen = (UINT32)length;
2496 PCSC_AddMemoryBlock(hContext, namePCSC);
2500 *pcbAttrLen = WINPR_ASSERTING_INT_CAST(uint32_t, length);
2501 if ((length > cbAttrLen) && pbAttr)
2502 status = SCARD_E_INSUFFICIENT_BUFFER;
2504 CopyMemory(pbAttr, namePCSC, length);
2513static LONG PCSC_ReadDeviceSystemNameGet(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, SCARDHANDLE hCard,
2514 DWORD dwAttrId, LPBYTE* pbAttr, LPDWORD pcbAttrLen)
2516 PCSC_DWORD cchReader = 0;
2517 PCSC_DWORD cbAtr = 0;
2518 PCSC_DWORD dwState = 0;
2519 PCSC_DWORD dwProtocol = 0;
2521 const PCSC_LONG rc =
2522 g_PCSC.pfnSCardStatus(hCard,
nullptr, &cchReader, &dwState, &dwProtocol,
nullptr, &cbAtr);
2523 if (rc != SCARD_S_SUCCESS)
2526 void* tmp = calloc(cchReader + 1,
sizeof(CHAR));
2528 return SCARD_E_NO_MEMORY;
2529 const PCSC_LONG rc2 =
2530 g_PCSC.pfnSCardStatus(hCard, tmp, &cchReader, &dwState, &dwProtocol,
nullptr, &cbAtr);
2531 if (rc2 != SCARD_S_SUCCESS)
2537 if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_W)
2540 void* data = ConvertMszUtf8NToWCharAlloc(tmp, cchReader, &len);
2544 return SCARD_E_NO_MEMORY;
2546 len *=
sizeof(WCHAR);
2548 cchReader = WINPR_ASSERTING_INT_CAST(PCSC_DWORD, len);
2554 *pcbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, cchReader);
2555 return SCARD_S_SUCCESS;
2558static LONG PCSC_ReadDeviceSystemName(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, SCARDHANDLE hCard,
2559 DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
2561 BYTE* tmp =
nullptr;
2562 DWORD cbAttrLen = 0;
2563 const LONG rc = PCSC_ReadDeviceSystemNameGet(hContext, hCard, dwAttrId, &tmp, &cbAttrLen);
2564 if (rc != SCARD_S_SUCCESS)
2567 if (*pcbAttrLen == SCARD_AUTOALLOCATE)
2569 if (!PCSC_AddMemoryBlock(hContext, tmp))
2572 return SCARD_E_NO_MEMORY;
2575 *pcbAttrLen = cbAttrLen;
2576 *(BYTE**)pbAttr = tmp;
2577 return SCARD_S_SUCCESS;
2581 memcpy(pbAttr, tmp, MIN(cbAttrLen, *pcbAttrLen));
2586 if (cbAttrLen > *pcbAttrLen)
2587 return SCARD_E_INSUFFICIENT_BUFFER;
2590 *pcbAttrLen = cbAttrLen;
2592 return SCARD_S_SUCCESS;
2595static LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
2598 DWORD cbAttrLen = 0;
2599 SCARDCONTEXT hContext = 0;
2600 BOOL pcbAttrLenAlloc = FALSE;
2601 PCSC_LONG status = SCARD_S_SUCCESS;
2603 if (
nullptr == pcbAttrLen)
2604 return SCARD_E_INVALID_PARAMETER;
2606 cbAttrLen = *pcbAttrLen;
2608 if (*pcbAttrLen == SCARD_AUTOALLOCATE)
2610 if (
nullptr == pbAttr)
2611 return SCARD_E_INVALID_PARAMETER;
2613 pcbAttrLenAlloc = TRUE;
2614 *(BYTE**)pbAttr =
nullptr;
2622 if (*pcbAttrLen > PCSC_MAX_BUFFER_SIZE)
2623 *pcbAttrLen = PCSC_MAX_BUFFER_SIZE;
2626 hContext = PCSC_GetCardContextFromHandle(hCard);
2629 return SCARD_E_INVALID_HANDLE;
2631 if ((dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A) ||
2632 (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W))
2634 return PCSC_SCardGetAttrib_FriendlyName(hCard, dwAttrId, pbAttr, pcbAttrLen);
2637 status = PCSC_SCardGetAttrib_Internal(hCard, dwAttrId, pbAttr, pcbAttrLen);
2639 if (status == SCARD_S_SUCCESS)
2641 if (dwAttrId == SCARD_ATTR_VENDOR_NAME)
2645 const char* vendorName =
nullptr;
2652 if (pcbAttrLenAlloc)
2653 vendorName = (
char*)*(BYTE**)pbAttr;
2655 vendorName = (
char*)pbAttr;
2659 size_t len = strnlen(vendorName, *pcbAttrLen);
2660 WINPR_ASSERT(len < UINT32_MAX);
2661 *pcbAttrLen = (DWORD)len + 1;
2670 if (dwAttrId == SCARD_ATTR_CURRENT_PROTOCOL_TYPE)
2672 if (!pcbAttrLenAlloc)
2674 PCSC_DWORD dwState = 0;
2675 PCSC_DWORD cbAtrLen = 0;
2676 PCSC_DWORD dwProtocol = 0;
2677 PCSC_DWORD cchReaderLen = 0;
2678 status = g_PCSC.pfnSCardStatus(hCard,
nullptr, &cchReaderLen, &dwState, &dwProtocol,
2679 nullptr, &cbAtrLen);
2681 if (status == SCARD_S_SUCCESS)
2683 if ((cbAttrLen <
sizeof(DWORD)) && pbAttr)
2684 return SCARD_E_INSUFFICIENT_BUFFER;
2687 *(DWORD*)pbAttr = PCSC_ConvertProtocolsToWinSCard(dwProtocol);
2688 *pcbAttrLen =
sizeof(DWORD);
2692 else if (dwAttrId == SCARD_ATTR_CHANNEL_ID)
2694 if (!pcbAttrLenAlloc)
2696 UINT32 channelType = 0x20;
2697 UINT32 channelNumber = 0;
2699 if ((cbAttrLen <
sizeof(DWORD)) && pbAttr)
2700 return SCARD_E_INSUFFICIENT_BUFFER;
2702 status = SCARD_S_SUCCESS;
2704 *(DWORD*)pbAttr = (channelType << 16u) | channelNumber;
2705 *pcbAttrLen =
sizeof(DWORD);
2708 else if (dwAttrId == SCARD_ATTR_VENDOR_IFD_TYPE)
2711 else if (dwAttrId == SCARD_ATTR_DEFAULT_CLK)
2714 else if (dwAttrId == SCARD_ATTR_DEFAULT_DATA_RATE)
2717 else if (dwAttrId == SCARD_ATTR_MAX_CLK)
2720 else if (dwAttrId == SCARD_ATTR_MAX_DATA_RATE)
2723 else if (dwAttrId == SCARD_ATTR_MAX_IFSD)
2726 else if (dwAttrId == SCARD_ATTR_CHARACTERISTICS)
2729 else if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_A)
2731 status = PCSC_ReadDeviceSystemName(hContext, hCard, dwAttrId, pbAttr, pcbAttrLen);
2733 else if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_W)
2735 status = PCSC_ReadDeviceSystemName(hContext, hCard, dwAttrId, pbAttr, pcbAttrLen);
2737 else if (dwAttrId == SCARD_ATTR_DEVICE_UNIT)
2740 else if (dwAttrId == SCARD_ATTR_POWER_MGMT_SUPPORT)
2743 else if (dwAttrId == SCARD_ATTR_CURRENT_CLK)
2746 else if (dwAttrId == SCARD_ATTR_CURRENT_F)
2749 else if (dwAttrId == SCARD_ATTR_CURRENT_D)
2752 else if (dwAttrId == SCARD_ATTR_CURRENT_N)
2755 else if (dwAttrId == SCARD_ATTR_CURRENT_CWT)
2758 else if (dwAttrId == SCARD_ATTR_CURRENT_BWT)
2761 else if (dwAttrId == SCARD_ATTR_CURRENT_IFSC)
2764 else if (dwAttrId == SCARD_ATTR_CURRENT_EBC_ENCODING)
2767 else if (dwAttrId == SCARD_ATTR_CURRENT_IFSD)
2770 else if (dwAttrId == SCARD_ATTR_ICC_TYPE_PER_ATR)
2775 return WINPR_ASSERTING_INT_CAST(LONG, status);
2778static LONG WINAPI PCSC_SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
2781 PCSC_LONG status = SCARD_S_SUCCESS;
2782 PCSC_SCARDHANDLE* pCard =
nullptr;
2783 PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD)dwAttrId;
2784 PCSC_DWORD pcsc_cbAttrLen = (PCSC_DWORD)cbAttrLen;
2786 if (!g_PCSC.pfnSCardSetAttrib)
2787 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardSetAttrib");
2789 pCard = PCSC_GetCardHandleData(hCard);
2792 return SCARD_E_INVALID_VALUE;
2794 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2795 status = g_PCSC.pfnSCardSetAttrib(hCard, pcsc_dwAttrId, pbAttr, pcsc_cbAttrLen);
2796 return PCSC_MapErrorCodeToWinSCard(status);
2799static LONG WINAPI PCSC_SCardUIDlgSelectCardA(LPOPENCARDNAMEA_EX pDlgStruc)
2801 WINPR_UNUSED(pDlgStruc);
2803 return SCARD_E_UNSUPPORTED_FEATURE;
2806static LONG WINAPI PCSC_SCardUIDlgSelectCardW(LPOPENCARDNAMEW_EX pDlgStruc)
2808 WINPR_UNUSED(pDlgStruc);
2809 return SCARD_E_UNSUPPORTED_FEATURE;
2814 WINPR_UNUSED(pDlgStruc);
2815 return SCARD_E_UNSUPPORTED_FEATURE;
2820 WINPR_UNUSED(pDlgStruc);
2821 return SCARD_E_UNSUPPORTED_FEATURE;
2824static LONG WINAPI PCSC_SCardDlgExtendedError(
void)
2827 return SCARD_E_UNSUPPORTED_FEATURE;
2830static char* card_id_and_name_a(
const UUID* CardIdentifier, LPCSTR LookupName)
2832 WINPR_ASSERT(CardIdentifier);
2833 WINPR_ASSERT(LookupName);
2835 size_t len = strlen(LookupName) + 34;
2836 char*
id = malloc(len);
2840 (void)snprintf(
id, len,
"%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X\\%s",
2841 CardIdentifier->Data1, CardIdentifier->Data2, CardIdentifier->Data3,
2842 CardIdentifier->Data4[0], CardIdentifier->Data4[1], CardIdentifier->Data4[2],
2843 CardIdentifier->Data4[3], CardIdentifier->Data4[4], CardIdentifier->Data4[5],
2844 CardIdentifier->Data4[6], CardIdentifier->Data4[7], LookupName);
2848static char* card_id_and_name_w(
const UUID* CardIdentifier, LPCWSTR LookupName)
2850 char* res =
nullptr;
2851 char* tmp = ConvertWCharToUtf8Alloc(LookupName,
nullptr);
2854 res = card_id_and_name_a(CardIdentifier, tmp);
2859static LONG WINAPI PCSC_SCardReadCacheA(SCARDCONTEXT hContext,
UUID* CardIdentifier,
2860 DWORD FreshnessCounter, LPSTR LookupName, PBYTE Data,
2863 PCSC_CACHE_ITEM* data =
nullptr;
2864 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
2866 return SCARD_E_INVALID_HANDLE;
2868 char*
id = card_id_and_name_a(CardIdentifier, LookupName);
2870 data = HashTable_GetItemValue(ctx->cache,
id);
2875 return SCARD_W_CACHE_ITEM_NOT_FOUND;
2878 if (FreshnessCounter != data->freshness)
2881 return SCARD_W_CACHE_ITEM_STALE;
2884 if (*DataLen == SCARD_AUTOALLOCATE)
2886 BYTE* mem = calloc(1, data->len);
2888 return SCARD_E_NO_MEMORY;
2890 if (!PCSC_AddMemoryBlock(hContext, mem))
2893 return SCARD_E_NO_MEMORY;
2896 memcpy(mem, data->data, data->len);
2897 *(BYTE**)Data = mem;
2900 memcpy(Data, data->data, data->len);
2901 *DataLen = data->len;
2902 return SCARD_S_SUCCESS;
2905static LONG WINAPI PCSC_SCardReadCacheW(SCARDCONTEXT hContext,
UUID* CardIdentifier,
2906 DWORD FreshnessCounter, LPWSTR LookupName, PBYTE Data,
2909 PCSC_CACHE_ITEM* data =
nullptr;
2910 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
2912 return SCARD_E_INVALID_HANDLE;
2914 char*
id = card_id_and_name_w(CardIdentifier, LookupName);
2916 data = HashTable_GetItemValue(ctx->cache,
id);
2922 return SCARD_W_CACHE_ITEM_NOT_FOUND;
2925 if (FreshnessCounter != data->freshness)
2928 return SCARD_W_CACHE_ITEM_STALE;
2931 if (*DataLen == SCARD_AUTOALLOCATE)
2933 BYTE* mem = calloc(1, data->len);
2935 return SCARD_E_NO_MEMORY;
2937 if (!PCSC_AddMemoryBlock(hContext, mem))
2940 return SCARD_E_NO_MEMORY;
2943 memcpy(mem, data->data, data->len);
2944 *(BYTE**)Data = mem;
2947 memcpy(Data, data->data, data->len);
2948 *DataLen = data->len;
2949 return SCARD_S_SUCCESS;
2952static LONG WINAPI PCSC_SCardWriteCacheA(SCARDCONTEXT hContext,
UUID* CardIdentifier,
2953 DWORD FreshnessCounter, LPSTR LookupName, PBYTE Data,
2956 PCSC_CACHE_ITEM* data =
nullptr;
2957 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
2961 return SCARD_E_FILE_NOT_FOUND;
2963 id = card_id_and_name_a(CardIdentifier, LookupName);
2966 return SCARD_E_NO_MEMORY;
2968 data = malloc(
sizeof(PCSC_CACHE_ITEM));
2972 return SCARD_E_NO_MEMORY;
2974 data->data = calloc(DataLen, 1);
2979 return SCARD_E_NO_MEMORY;
2981 data->len = DataLen;
2982 data->freshness = FreshnessCounter;
2983 memcpy(data->data, Data, data->len);
2985 HashTable_Remove(ctx->cache,
id);
2986 const BOOL rc = HashTable_Insert(ctx->cache,
id, data);
2991 pcsc_cache_item_free(data);
2992 return SCARD_E_NO_MEMORY;
2996 return SCARD_S_SUCCESS;
2999static LONG WINAPI PCSC_SCardWriteCacheW(SCARDCONTEXT hContext,
UUID* CardIdentifier,
3000 DWORD FreshnessCounter, LPWSTR LookupName, PBYTE Data,
3003 PCSC_CACHE_ITEM* data =
nullptr;
3004 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
3007 return SCARD_E_FILE_NOT_FOUND;
3009 id = card_id_and_name_w(CardIdentifier, LookupName);
3012 return SCARD_E_NO_MEMORY;
3014 data = malloc(
sizeof(PCSC_CACHE_ITEM));
3018 return SCARD_E_NO_MEMORY;
3020 data->data = malloc(DataLen);
3025 return SCARD_E_NO_MEMORY;
3027 data->len = DataLen;
3028 data->freshness = FreshnessCounter;
3029 memcpy(data->data, Data, data->len);
3031 HashTable_Remove(ctx->cache,
id);
3032 const BOOL rc = HashTable_Insert(ctx->cache,
id, data);
3037 pcsc_cache_item_free(data);
3038 return SCARD_E_NO_MEMORY;
3042 return SCARD_S_SUCCESS;
3045static LONG WINAPI PCSC_SCardGetReaderIconA(
3046 SCARDCONTEXT hContext, LPCSTR szReaderName,
3047 LPBYTE pbIcon , LPDWORD pcbIcon)
3049 WINPR_UNUSED(hContext);
3050 WINPR_UNUSED(szReaderName);
3051 WINPR_UNUSED(pbIcon);
3052 WINPR_ASSERT(pcbIcon);
3054 return SCARD_E_UNSUPPORTED_FEATURE;
3057static LONG WINAPI PCSC_SCardGetReaderIconW(
3058 SCARDCONTEXT hContext, LPCWSTR szReaderName,
3059 LPBYTE pbIcon , LPDWORD pcbIcon)
3061 WINPR_UNUSED(hContext);
3062 WINPR_UNUSED(szReaderName);
3063 WINPR_UNUSED(pbIcon);
3064 WINPR_ASSERT(pcbIcon);
3066 return SCARD_E_UNSUPPORTED_FEATURE;
3069static LONG WINAPI PCSC_SCardGetDeviceTypeIdA(SCARDCONTEXT hContext, LPCSTR szReaderName,
3070 LPDWORD pdwDeviceTypeId)
3072 WINPR_UNUSED(hContext);
3073 WINPR_UNUSED(szReaderName);
3074 WINPR_UNUSED(pdwDeviceTypeId);
3075 if (pdwDeviceTypeId)
3076 *pdwDeviceTypeId = SCARD_READER_TYPE_USB;
3077 return SCARD_S_SUCCESS;
3080static LONG WINAPI PCSC_SCardGetDeviceTypeIdW(SCARDCONTEXT hContext, LPCWSTR szReaderName,
3081 LPDWORD pdwDeviceTypeId)
3083 WINPR_UNUSED(hContext);
3084 WINPR_UNUSED(szReaderName);
3085 if (pdwDeviceTypeId)
3086 *pdwDeviceTypeId = SCARD_READER_TYPE_USB;
3087 return SCARD_S_SUCCESS;
3090static LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdA(
3091 SCARDCONTEXT hContext, LPCSTR szReaderName,
3092 LPSTR szDeviceInstanceId ,
3093 LPDWORD pcchDeviceInstanceId )
3095 WINPR_UNUSED(hContext);
3096 WINPR_UNUSED(szReaderName);
3097 WINPR_UNUSED(szDeviceInstanceId);
3098 WINPR_UNUSED(pcchDeviceInstanceId);
3099 return SCARD_E_UNSUPPORTED_FEATURE;
3102static LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdW(
3103 SCARDCONTEXT hContext, LPCWSTR szReaderName,
3104 LPWSTR szDeviceInstanceId ,
3105 LPDWORD pcchDeviceInstanceId )
3107 WINPR_UNUSED(hContext);
3108 WINPR_UNUSED(szReaderName);
3109 WINPR_UNUSED(szDeviceInstanceId);
3110 WINPR_UNUSED(pcchDeviceInstanceId);
3111 return SCARD_E_UNSUPPORTED_FEATURE;
3114static LONG WINAPI PCSC_SCardListReadersWithDeviceInstanceIdA(
3115 SCARDCONTEXT hContext, LPCSTR szDeviceInstanceId,
3117 LPDWORD pcchReaders )
3119 WINPR_UNUSED(hContext);
3120 WINPR_UNUSED(szDeviceInstanceId);
3121 WINPR_UNUSED(mszReaders);
3122 WINPR_UNUSED(pcchReaders);
3123 return SCARD_E_UNSUPPORTED_FEATURE;
3126static LONG WINAPI PCSC_SCardListReadersWithDeviceInstanceIdW(
3127 SCARDCONTEXT hContext, LPCWSTR szDeviceInstanceId,
3129 LPDWORD pcchReaders )
3131 WINPR_UNUSED(hContext);
3132 WINPR_UNUSED(szDeviceInstanceId);
3133 WINPR_UNUSED(mszReaders);
3134 WINPR_UNUSED(pcchReaders);
3135 return SCARD_E_UNSUPPORTED_FEATURE;
3138static LONG WINAPI PCSC_SCardAudit(SCARDCONTEXT hContext, DWORD dwEvent)
3141 WINPR_UNUSED(hContext);
3142 WINPR_UNUSED(dwEvent);
3143 return SCARD_E_UNSUPPORTED_FEATURE;
3147unsigned int determineMacOSXVersion(
void)
3151 char* kernelVersion =
nullptr;
3152 char* tok =
nullptr;
3153 unsigned int version = 0;
3154 long majorVersion = 0;
3155 long minorVersion = 0;
3156 long patchVersion = 0;
3158 char* context =
nullptr;
3160 mib[1] = KERN_OSRELEASE;
3162 if (sysctl(mib, 2,
nullptr, &len,
nullptr, 0) != 0)
3165 kernelVersion = calloc(len,
sizeof(
char));
3170 if (sysctl(mib, 2, kernelVersion, &len,
nullptr, 0) != 0)
3172 free(kernelVersion);
3176 tok = strtok_s(kernelVersion,
".", &context);
3184 majorVersion = strtol(tok,
nullptr, 0);
3192 minorVersion = strtol(tok,
nullptr, 0);
3200 patchVersion = strtol(tok,
nullptr, 0);
3208 tok = strtok_s(
nullptr,
".", &context);
3215 if (majorVersion < 5)
3217 if (minorVersion < 4)
3218 version = 0x10000000;
3220 version = 0x10010000;
3224 switch (majorVersion)
3227 version = 0x10010000;
3231 version = 0x10020000;
3235 version = 0x10030000;
3239 version = 0x10040000;
3243 version = 0x10050000;
3247 version = 0x10060000;
3251 version = 0x10070000;
3255 version = 0x10080000;
3259 version = 0x10090000;
3263 version = 0x10100000;
3267 version |= (minorVersion << 8) | (patchVersion);
3271 free(kernelVersion);
3280 PCSC_SCardEstablishContext,
3281 PCSC_SCardReleaseContext,
3282 PCSC_SCardIsValidContext,
3283 PCSC_SCardListReaderGroupsA,
3284 PCSC_SCardListReaderGroupsW,
3285 PCSC_SCardListReadersA,
3286 PCSC_SCardListReadersW,
3287 PCSC_SCardListCardsA,
3288 PCSC_SCardListCardsW,
3289 PCSC_SCardListInterfacesA,
3290 PCSC_SCardListInterfacesW,
3291 PCSC_SCardGetProviderIdA,
3292 PCSC_SCardGetProviderIdW,
3293 PCSC_SCardGetCardTypeProviderNameA,
3294 PCSC_SCardGetCardTypeProviderNameW,
3295 PCSC_SCardIntroduceReaderGroupA,
3296 PCSC_SCardIntroduceReaderGroupW,
3297 PCSC_SCardForgetReaderGroupA,
3298 PCSC_SCardForgetReaderGroupW,
3299 PCSC_SCardIntroduceReaderA,
3300 PCSC_SCardIntroduceReaderW,
3301 PCSC_SCardForgetReaderA,
3302 PCSC_SCardForgetReaderW,
3303 PCSC_SCardAddReaderToGroupA,
3304 PCSC_SCardAddReaderToGroupW,
3305 PCSC_SCardRemoveReaderFromGroupA,
3306 PCSC_SCardRemoveReaderFromGroupW,
3307 PCSC_SCardIntroduceCardTypeA,
3308 PCSC_SCardIntroduceCardTypeW,
3309 PCSC_SCardSetCardTypeProviderNameA,
3310 PCSC_SCardSetCardTypeProviderNameW,
3311 PCSC_SCardForgetCardTypeA,
3312 PCSC_SCardForgetCardTypeW,
3313 PCSC_SCardFreeMemory,
3314 PCSC_SCardAccessStartedEvent,
3315 PCSC_SCardReleaseStartedEvent,
3316 PCSC_SCardLocateCardsA,
3317 PCSC_SCardLocateCardsW,
3318 PCSC_SCardLocateCardsByATRA,
3319 PCSC_SCardLocateCardsByATRW,
3320 PCSC_SCardGetStatusChangeA,
3321 PCSC_SCardGetStatusChangeW,
3325 PCSC_SCardReconnect,
3326 PCSC_SCardDisconnect,
3327 PCSC_SCardBeginTransaction,
3328 PCSC_SCardEndTransaction,
3329 PCSC_SCardCancelTransaction,
3334 PCSC_SCardGetTransmitCount,
3336 PCSC_SCardGetAttrib,
3337 PCSC_SCardSetAttrib,
3338 PCSC_SCardUIDlgSelectCardA,
3339 PCSC_SCardUIDlgSelectCardW,
3340 PCSC_GetOpenCardNameA,
3341 PCSC_GetOpenCardNameW,
3342 PCSC_SCardDlgExtendedError,
3343 PCSC_SCardReadCacheA,
3344 PCSC_SCardReadCacheW,
3345 PCSC_SCardWriteCacheA,
3346 PCSC_SCardWriteCacheW,
3347 PCSC_SCardGetReaderIconA,
3348 PCSC_SCardGetReaderIconW,
3349 PCSC_SCardGetDeviceTypeIdA,
3350 PCSC_SCardGetDeviceTypeIdW,
3351 PCSC_SCardGetReaderDeviceInstanceIdA,
3352 PCSC_SCardGetReaderDeviceInstanceIdW,
3353 PCSC_SCardListReadersWithDeviceInstanceIdA,
3354 PCSC_SCardListReadersWithDeviceInstanceIdW,
3360 return &PCSC_SCardApiFunctionTable;
3363int PCSC_InitializeSCardApi(
void)
3366 SetEnvironmentVariableA(
"PCSCLITE_NO_BLOCKING",
"1");
3368 g_PCSCModule = LoadLibraryX(
"/System/Library/Frameworks/PCSC.framework/PCSC");
3369 OSXVersion = determineMacOSXVersion();
3371 if (OSXVersion == 0)
3375 g_PCSCModule = LoadLibraryA(
"libpcsclite.so.1");
3378 g_PCSCModule = LoadLibraryA(
"libpcsclite.so");
3387#undef SCardListReaderGroups
3388#undef SCardListReaders
3389#undef SCardListCards
3390#undef SCardListInterfaces
3391#undef SCardGetProviderId
3392#undef SCardGetCardTypeProviderName
3393#undef SCardIntroduceReaderGroup
3394#undef SCardForgetReaderGroup
3395#undef SCardIntroduceReader
3396#undef SCardForgetReader
3397#undef SCardAddReaderToGroup
3398#undef SCardRemoveReaderFromGroup
3399#undef SCardIntroduceCardType
3400#undef SCardSetCardTypeProviderName
3401#undef SCardForgetCardType
3402#undef SCardLocateCards
3403#undef SCardLocateCardsByATR
3404#undef SCardGetStatusChange
3407#undef SCardUIDlgSelectCard
3408#undef GetOpenCardName
3409#undef SCardReadCache
3410#undef SCardWriteCache
3411#undef SCardGetReaderIcon
3412#undef SCardGetDeviceTypeId
3413#undef SCardGetReaderDeviceInstanceId
3414#undef SCardListReadersWithDeviceInstanceId
3416 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardEstablishContext);
3417 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardReleaseContext);
3418 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardIsValidContext);
3419 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardConnect);
3420 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardReconnect);
3421 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardDisconnect);
3422 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardBeginTransaction);
3423 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardEndTransaction);
3424 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardStatus);
3425 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardGetStatusChange);
3429 if (OSXVersion >= 0x10050600)
3431 WINSCARD_LOAD_PROC_EX(g_PCSCModule, g_PCSC, SCardControl, SCardControl132);
3435 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardControl);
3438 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardControl);
3440 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardTransmit);
3441 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardListReaderGroups);
3442 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardListReaders);
3443 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardCancel);
3444 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardGetAttrib);
3445 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardSetAttrib);
3446 g_PCSC.pfnSCardFreeMemory =
nullptr;
3448 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardFreeMemory);
3451 if (g_PCSC.pfnSCardFreeMemory)
3452 g_SCardAutoAllocate = TRUE;
3454#ifdef DISABLE_PCSC_SCARD_AUTOALLOCATE
3455 g_PCSC.pfnSCardFreeMemory =
nullptr;
3456 g_SCardAutoAllocate = FALSE;
3459 g_PnP_Notification = FALSE;
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree