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 = NULL;
221static PCSCFunctionTable g_PCSC = { 0 };
223static HANDLE g_StartedEvent = NULL;
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 = NULL;
234static wListDictionary* g_CardContexts = NULL;
235static wListDictionary* g_MemoryBlocks = NULL;
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=NULL", 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 = NULL;
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 = NULL;
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 = NULL;
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 = NULL;
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 = NULL;
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 = NULL;
494 pCard = (PCSC_SCARDHANDLE*)ListDictionary_GetItemValue(g_CardHandles, (
void*)hCard);
502static SCARDCONTEXT PCSC_GetCardContextFromHandle(SCARDHANDLE hCard)
504 PCSC_SCARDHANDLE* pCard = NULL;
505 pCard = PCSC_GetCardHandleData(hCard);
510 return pCard->hSharedContext;
513static BOOL PCSC_WaitForCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard, BOOL shared)
516 PCSC_SCARDHANDLE* pCard = NULL;
517 PCSC_SCARDCONTEXT* pContext = NULL;
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 = NULL;
570 PCSC_SCARDCONTEXT* pContext = NULL;
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 = NULL;
618 PCSC_SCARDCONTEXT* pContext = NULL;
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 = NULL;
655 PCSC_SCARDCONTEXT* pContext = NULL;
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, NULL, &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 = NULL;
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, NULL, &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, NULL, NULL, &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 = NULL;
969 LPSTR mszReadersA = NULL;
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, NULL, NULL, &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, NULL);
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 = NULL;
1069 DWORD outputLen = 1;
1070 CHAR* output = NULL;
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 = NULL;
1122 DWORD outputLen = 1;
1123 WCHAR* output = NULL;
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, NULL, NULL, &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(NULL, TRUE, FALSE, NULL)))
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 = NULL;
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,
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, NULL);
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 = NULL;
1713 PCSC_LONG status = SCARD_S_SUCCESS;
1714 PCSC_SCARDHANDLE* pCard = NULL;
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) ? TRUE : FALSE;
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 = NULL;
1778 LONG status = SCARD_S_SUCCESS;
1780 if (!PCSC_LockCardContext(hContext))
1781 return SCARD_E_INVALID_HANDLE;
1785 szReaderA = ConvertWCharToUtf8Alloc(szReader, NULL);
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) ? TRUE : FALSE;
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 = NULL;
1847 PCSC_SCARDCONTEXT* pContext = NULL;
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 = NULL;
1875 PCSC_SCARDCONTEXT* pContext = NULL;
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 = NULL;
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 = NULL;
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;
1946 g_PCSC.pfnSCardStatus(hCard, NULL, &pcsc_cchReaderLen, NULL, NULL, NULL, &pcsc_cbAtrLen);
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 = NULL;
2079 PCSC_LONG status = SCARD_S_SUCCESS;
2080 PCSC_SCARDHANDLE* pCard = NULL;
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 = NULL;
2141 PCSC_DWORD cbExtraBytes = 0;
2142 BYTE* pbExtraBytes = NULL;
2143 BYTE* pcsc_pbExtraBytes = NULL;
2144 PCSC_DWORD pcsc_cbSendLength = (PCSC_DWORD)cbSendLength;
2145 PCSC_DWORD pcsc_cbRecvLength = 0;
2153 } sendPci, recvPci, inRecvPci, inSendPci;
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, NULL, &cchReaderLen, &dwState, &dwProtocol, NULL,
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 = NULL;
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 = NULL;
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 = NULL;
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, NULL, &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 = NULL;
2415 char* pbAttrA = NULL;
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 = NULL;
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, NULL);
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_ReadDeviceSystemName(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, SCARDHANDLE hCard,
2514 DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
2517 PCSC_DWORD dwState = 0;
2518 PCSC_DWORD dwProtocol = 0;
2521 DWORD cbAttrLen = *pcbAttrLen;
2522 if (cbAttrLen == SCARD_AUTOALLOCATE)
2523 return SCARD_E_UNEXPECTED;
2525 if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_W)
2526 cbAttrLen /=
sizeof(WCHAR);
2528 PCSC_DWORD cbAtr = 0;
2529 PCSC_DWORD cchReader = cbAttrLen;
2530 const PCSC_LONG rc = g_PCSC.pfnSCardStatus(hCard, (LPSTR)pbAttr, &cchReader, &dwState,
2531 &dwProtocol, NULL, &cbAtr);
2533 *pcbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, cchReader);
2534 status = WINPR_ASSERTING_INT_CAST(LONG, rc);
2535 if (status != SCARD_S_SUCCESS)
2538 if (cchReader > cbAttrLen)
2539 return SCARD_E_INSUFFICIENT_BUFFER;
2541 if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_W)
2544 WCHAR* tmp = ConvertMszUtf8NToWCharAlloc((LPSTR)pbAttr, cchReader, &wlen);
2546 return SCARD_E_NO_MEMORY;
2549 if (wlen > cbAttrLen)
2552 return SCARD_E_INSUFFICIENT_BUFFER;
2554 *pcbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, MIN(wlen, cchReader) *
sizeof(WCHAR));
2555 memcpy(pbAttr, tmp, *pcbAttrLen);
2562static LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
2565 DWORD cbAttrLen = 0;
2566 SCARDCONTEXT hContext = 0;
2567 BOOL pcbAttrLenAlloc = FALSE;
2568 PCSC_LONG status = SCARD_S_SUCCESS;
2570 if (NULL == pcbAttrLen)
2571 return SCARD_E_INVALID_PARAMETER;
2573 cbAttrLen = *pcbAttrLen;
2575 if (*pcbAttrLen == SCARD_AUTOALLOCATE)
2578 return SCARD_E_INVALID_PARAMETER;
2580 pcbAttrLenAlloc = TRUE;
2581 *(BYTE**)pbAttr = NULL;
2589 if (*pcbAttrLen > PCSC_MAX_BUFFER_SIZE)
2590 *pcbAttrLen = PCSC_MAX_BUFFER_SIZE;
2593 hContext = PCSC_GetCardContextFromHandle(hCard);
2596 return SCARD_E_INVALID_HANDLE;
2598 if ((dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A) ||
2599 (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W))
2601 return PCSC_SCardGetAttrib_FriendlyName(hCard, dwAttrId, pbAttr, pcbAttrLen);
2604 status = PCSC_SCardGetAttrib_Internal(hCard, dwAttrId, pbAttr, pcbAttrLen);
2606 if (status == SCARD_S_SUCCESS)
2608 if (dwAttrId == SCARD_ATTR_VENDOR_NAME)
2612 const char* vendorName = NULL;
2619 if (pcbAttrLenAlloc)
2620 vendorName = (
char*)*(BYTE**)pbAttr;
2622 vendorName = (
char*)pbAttr;
2626 size_t len = strnlen(vendorName, *pcbAttrLen);
2627 WINPR_ASSERT(len < UINT32_MAX);
2628 *pcbAttrLen = (DWORD)len + 1;
2637 if (dwAttrId == SCARD_ATTR_CURRENT_PROTOCOL_TYPE)
2639 if (!pcbAttrLenAlloc)
2641 PCSC_DWORD dwState = 0;
2642 PCSC_DWORD cbAtrLen = 0;
2643 PCSC_DWORD dwProtocol = 0;
2644 PCSC_DWORD cchReaderLen = 0;
2645 status = g_PCSC.pfnSCardStatus(hCard, NULL, &cchReaderLen, &dwState, &dwProtocol,
2648 if (status == SCARD_S_SUCCESS)
2650 if ((cbAttrLen <
sizeof(DWORD)) && pbAttr)
2651 return SCARD_E_INSUFFICIENT_BUFFER;
2654 *(DWORD*)pbAttr = PCSC_ConvertProtocolsToWinSCard(dwProtocol);
2655 *pcbAttrLen =
sizeof(DWORD);
2659 else if (dwAttrId == SCARD_ATTR_CHANNEL_ID)
2661 if (!pcbAttrLenAlloc)
2663 UINT32 channelType = 0x20;
2664 UINT32 channelNumber = 0;
2666 if ((cbAttrLen <
sizeof(DWORD)) && pbAttr)
2667 return SCARD_E_INSUFFICIENT_BUFFER;
2669 status = SCARD_S_SUCCESS;
2671 *(DWORD*)pbAttr = (channelType << 16u) | channelNumber;
2672 *pcbAttrLen =
sizeof(DWORD);
2675 else if (dwAttrId == SCARD_ATTR_VENDOR_IFD_TYPE)
2678 else if (dwAttrId == SCARD_ATTR_DEFAULT_CLK)
2681 else if (dwAttrId == SCARD_ATTR_DEFAULT_DATA_RATE)
2684 else if (dwAttrId == SCARD_ATTR_MAX_CLK)
2687 else if (dwAttrId == SCARD_ATTR_MAX_DATA_RATE)
2690 else if (dwAttrId == SCARD_ATTR_MAX_IFSD)
2693 else if (dwAttrId == SCARD_ATTR_CHARACTERISTICS)
2696 else if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_A)
2698 if (!pcbAttrLenAlloc)
2699 status = PCSC_ReadDeviceSystemName(hContext, hCard, dwAttrId, pbAttr, pcbAttrLen);
2701 else if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_W)
2703 if (!pcbAttrLenAlloc)
2704 status = PCSC_ReadDeviceSystemName(hContext, hCard, dwAttrId, pbAttr, pcbAttrLen);
2706 else if (dwAttrId == SCARD_ATTR_DEVICE_UNIT)
2709 else if (dwAttrId == SCARD_ATTR_POWER_MGMT_SUPPORT)
2712 else if (dwAttrId == SCARD_ATTR_CURRENT_CLK)
2715 else if (dwAttrId == SCARD_ATTR_CURRENT_F)
2718 else if (dwAttrId == SCARD_ATTR_CURRENT_D)
2721 else if (dwAttrId == SCARD_ATTR_CURRENT_N)
2724 else if (dwAttrId == SCARD_ATTR_CURRENT_CWT)
2727 else if (dwAttrId == SCARD_ATTR_CURRENT_BWT)
2730 else if (dwAttrId == SCARD_ATTR_CURRENT_IFSC)
2733 else if (dwAttrId == SCARD_ATTR_CURRENT_EBC_ENCODING)
2736 else if (dwAttrId == SCARD_ATTR_CURRENT_IFSD)
2739 else if (dwAttrId == SCARD_ATTR_ICC_TYPE_PER_ATR)
2744 return WINPR_ASSERTING_INT_CAST(LONG, status);
2747static LONG WINAPI PCSC_SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
2750 PCSC_LONG status = SCARD_S_SUCCESS;
2751 PCSC_SCARDHANDLE* pCard = NULL;
2752 PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD)dwAttrId;
2753 PCSC_DWORD pcsc_cbAttrLen = (PCSC_DWORD)cbAttrLen;
2755 if (!g_PCSC.pfnSCardSetAttrib)
2756 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardSetAttrib");
2758 pCard = PCSC_GetCardHandleData(hCard);
2761 return SCARD_E_INVALID_VALUE;
2763 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2764 status = g_PCSC.pfnSCardSetAttrib(hCard, pcsc_dwAttrId, pbAttr, pcsc_cbAttrLen);
2765 return PCSC_MapErrorCodeToWinSCard(status);
2768static LONG WINAPI PCSC_SCardUIDlgSelectCardA(LPOPENCARDNAMEA_EX pDlgStruc)
2770 WINPR_UNUSED(pDlgStruc);
2772 return SCARD_E_UNSUPPORTED_FEATURE;
2775static LONG WINAPI PCSC_SCardUIDlgSelectCardW(LPOPENCARDNAMEW_EX pDlgStruc)
2777 WINPR_UNUSED(pDlgStruc);
2778 return SCARD_E_UNSUPPORTED_FEATURE;
2783 WINPR_UNUSED(pDlgStruc);
2784 return SCARD_E_UNSUPPORTED_FEATURE;
2789 WINPR_UNUSED(pDlgStruc);
2790 return SCARD_E_UNSUPPORTED_FEATURE;
2793static LONG WINAPI PCSC_SCardDlgExtendedError(
void)
2796 return SCARD_E_UNSUPPORTED_FEATURE;
2799static char* card_id_and_name_a(
const UUID* CardIdentifier, LPCSTR LookupName)
2801 WINPR_ASSERT(CardIdentifier);
2802 WINPR_ASSERT(LookupName);
2804 size_t len = strlen(LookupName) + 34;
2805 char*
id = malloc(len);
2809 (void)snprintf(
id, len,
"%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X\\%s",
2810 CardIdentifier->Data1, CardIdentifier->Data2, CardIdentifier->Data3,
2811 CardIdentifier->Data4[0], CardIdentifier->Data4[1], CardIdentifier->Data4[2],
2812 CardIdentifier->Data4[3], CardIdentifier->Data4[4], CardIdentifier->Data4[5],
2813 CardIdentifier->Data4[6], CardIdentifier->Data4[7], LookupName);
2817static char* card_id_and_name_w(
const UUID* CardIdentifier, LPCWSTR LookupName)
2820 char* tmp = ConvertWCharToUtf8Alloc(LookupName, NULL);
2823 res = card_id_and_name_a(CardIdentifier, tmp);
2828static LONG WINAPI PCSC_SCardReadCacheA(SCARDCONTEXT hContext,
UUID* CardIdentifier,
2829 DWORD FreshnessCounter, LPSTR LookupName, PBYTE Data,
2832 PCSC_CACHE_ITEM* data = NULL;
2833 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
2835 return SCARD_E_INVALID_HANDLE;
2837 char*
id = card_id_and_name_a(CardIdentifier, LookupName);
2839 data = HashTable_GetItemValue(ctx->cache,
id);
2844 return SCARD_W_CACHE_ITEM_NOT_FOUND;
2847 if (FreshnessCounter != data->freshness)
2850 return SCARD_W_CACHE_ITEM_STALE;
2853 if (*DataLen == SCARD_AUTOALLOCATE)
2855 BYTE* mem = calloc(1, data->len);
2857 return SCARD_E_NO_MEMORY;
2859 if (!PCSC_AddMemoryBlock(hContext, mem))
2862 return SCARD_E_NO_MEMORY;
2865 memcpy(mem, data->data, data->len);
2866 *(BYTE**)Data = mem;
2869 memcpy(Data, data->data, data->len);
2870 *DataLen = data->len;
2871 return SCARD_S_SUCCESS;
2874static LONG WINAPI PCSC_SCardReadCacheW(SCARDCONTEXT hContext,
UUID* CardIdentifier,
2875 DWORD FreshnessCounter, LPWSTR LookupName, PBYTE Data,
2878 PCSC_CACHE_ITEM* data = NULL;
2879 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
2881 return SCARD_E_INVALID_HANDLE;
2883 char*
id = card_id_and_name_w(CardIdentifier, LookupName);
2885 data = HashTable_GetItemValue(ctx->cache,
id);
2891 return SCARD_W_CACHE_ITEM_NOT_FOUND;
2894 if (FreshnessCounter != data->freshness)
2897 return SCARD_W_CACHE_ITEM_STALE;
2900 if (*DataLen == SCARD_AUTOALLOCATE)
2902 BYTE* mem = calloc(1, data->len);
2904 return SCARD_E_NO_MEMORY;
2906 if (!PCSC_AddMemoryBlock(hContext, mem))
2909 return SCARD_E_NO_MEMORY;
2912 memcpy(mem, data->data, data->len);
2913 *(BYTE**)Data = mem;
2916 memcpy(Data, data->data, data->len);
2917 *DataLen = data->len;
2918 return SCARD_S_SUCCESS;
2921static LONG WINAPI PCSC_SCardWriteCacheA(SCARDCONTEXT hContext,
UUID* CardIdentifier,
2922 DWORD FreshnessCounter, LPSTR LookupName, PBYTE Data,
2925 PCSC_CACHE_ITEM* data = NULL;
2926 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
2930 return SCARD_E_FILE_NOT_FOUND;
2932 id = card_id_and_name_a(CardIdentifier, LookupName);
2935 return SCARD_E_NO_MEMORY;
2937 data = malloc(
sizeof(PCSC_CACHE_ITEM));
2941 return SCARD_E_NO_MEMORY;
2943 data->data = calloc(DataLen, 1);
2948 return SCARD_E_NO_MEMORY;
2950 data->len = DataLen;
2951 data->freshness = FreshnessCounter;
2952 memcpy(data->data, Data, data->len);
2954 HashTable_Remove(ctx->cache,
id);
2955 const BOOL rc = HashTable_Insert(ctx->cache,
id, data);
2960 pcsc_cache_item_free(data);
2961 return SCARD_E_NO_MEMORY;
2965 return SCARD_S_SUCCESS;
2968static LONG WINAPI PCSC_SCardWriteCacheW(SCARDCONTEXT hContext,
UUID* CardIdentifier,
2969 DWORD FreshnessCounter, LPWSTR LookupName, PBYTE Data,
2972 PCSC_CACHE_ITEM* data = NULL;
2973 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
2976 return SCARD_E_FILE_NOT_FOUND;
2978 id = card_id_and_name_w(CardIdentifier, LookupName);
2981 return SCARD_E_NO_MEMORY;
2983 data = malloc(
sizeof(PCSC_CACHE_ITEM));
2987 return SCARD_E_NO_MEMORY;
2989 data->data = malloc(DataLen);
2994 return SCARD_E_NO_MEMORY;
2996 data->len = DataLen;
2997 data->freshness = FreshnessCounter;
2998 memcpy(data->data, Data, data->len);
3000 HashTable_Remove(ctx->cache,
id);
3001 const BOOL rc = HashTable_Insert(ctx->cache,
id, data);
3006 pcsc_cache_item_free(data);
3007 return SCARD_E_NO_MEMORY;
3011 return SCARD_S_SUCCESS;
3014static LONG WINAPI PCSC_SCardGetReaderIconA(
3015 SCARDCONTEXT hContext, LPCSTR szReaderName,
3016 LPBYTE pbIcon , LPDWORD pcbIcon)
3018 WINPR_UNUSED(hContext);
3019 WINPR_UNUSED(szReaderName);
3020 WINPR_UNUSED(pbIcon);
3021 WINPR_ASSERT(pcbIcon);
3023 return SCARD_E_UNSUPPORTED_FEATURE;
3026static LONG WINAPI PCSC_SCardGetReaderIconW(
3027 SCARDCONTEXT hContext, LPCWSTR szReaderName,
3028 LPBYTE pbIcon , LPDWORD pcbIcon)
3030 WINPR_UNUSED(hContext);
3031 WINPR_UNUSED(szReaderName);
3032 WINPR_UNUSED(pbIcon);
3033 WINPR_ASSERT(pcbIcon);
3035 return SCARD_E_UNSUPPORTED_FEATURE;
3038static LONG WINAPI PCSC_SCardGetDeviceTypeIdA(SCARDCONTEXT hContext, LPCSTR szReaderName,
3039 LPDWORD pdwDeviceTypeId)
3041 WINPR_UNUSED(hContext);
3042 WINPR_UNUSED(szReaderName);
3043 WINPR_UNUSED(pdwDeviceTypeId);
3044 if (pdwDeviceTypeId)
3045 *pdwDeviceTypeId = SCARD_READER_TYPE_USB;
3046 return SCARD_S_SUCCESS;
3049static LONG WINAPI PCSC_SCardGetDeviceTypeIdW(SCARDCONTEXT hContext, LPCWSTR szReaderName,
3050 LPDWORD pdwDeviceTypeId)
3052 WINPR_UNUSED(hContext);
3053 WINPR_UNUSED(szReaderName);
3054 if (pdwDeviceTypeId)
3055 *pdwDeviceTypeId = SCARD_READER_TYPE_USB;
3056 return SCARD_S_SUCCESS;
3059static LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdA(
3060 SCARDCONTEXT hContext, LPCSTR szReaderName,
3061 LPSTR szDeviceInstanceId ,
3062 LPDWORD pcchDeviceInstanceId )
3064 WINPR_UNUSED(hContext);
3065 WINPR_UNUSED(szReaderName);
3066 WINPR_UNUSED(szDeviceInstanceId);
3067 WINPR_UNUSED(pcchDeviceInstanceId);
3068 return SCARD_E_UNSUPPORTED_FEATURE;
3071static LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdW(
3072 SCARDCONTEXT hContext, LPCWSTR szReaderName,
3073 LPWSTR szDeviceInstanceId ,
3074 LPDWORD pcchDeviceInstanceId )
3076 WINPR_UNUSED(hContext);
3077 WINPR_UNUSED(szReaderName);
3078 WINPR_UNUSED(szDeviceInstanceId);
3079 WINPR_UNUSED(pcchDeviceInstanceId);
3080 return SCARD_E_UNSUPPORTED_FEATURE;
3083static LONG WINAPI PCSC_SCardListReadersWithDeviceInstanceIdA(
3084 SCARDCONTEXT hContext, LPCSTR szDeviceInstanceId,
3086 LPDWORD pcchReaders )
3088 WINPR_UNUSED(hContext);
3089 WINPR_UNUSED(szDeviceInstanceId);
3090 WINPR_UNUSED(mszReaders);
3091 WINPR_UNUSED(pcchReaders);
3092 return SCARD_E_UNSUPPORTED_FEATURE;
3095static LONG WINAPI PCSC_SCardListReadersWithDeviceInstanceIdW(
3096 SCARDCONTEXT hContext, LPCWSTR szDeviceInstanceId,
3098 LPDWORD pcchReaders )
3100 WINPR_UNUSED(hContext);
3101 WINPR_UNUSED(szDeviceInstanceId);
3102 WINPR_UNUSED(mszReaders);
3103 WINPR_UNUSED(pcchReaders);
3104 return SCARD_E_UNSUPPORTED_FEATURE;
3107static LONG WINAPI PCSC_SCardAudit(SCARDCONTEXT hContext, DWORD dwEvent)
3110 WINPR_UNUSED(hContext);
3111 WINPR_UNUSED(dwEvent);
3112 return SCARD_E_UNSUPPORTED_FEATURE;
3116unsigned int determineMacOSXVersion(
void)
3120 char* kernelVersion = NULL;
3122 unsigned int version = 0;
3123 long majorVersion = 0;
3124 long minorVersion = 0;
3125 long patchVersion = 0;
3127 char* context = NULL;
3129 mib[1] = KERN_OSRELEASE;
3131 if (sysctl(mib, 2, NULL, &len, NULL, 0) != 0)
3134 kernelVersion = calloc(len,
sizeof(
char));
3139 if (sysctl(mib, 2, kernelVersion, &len, NULL, 0) != 0)
3141 free(kernelVersion);
3145 tok = strtok_s(kernelVersion,
".", &context);
3153 majorVersion = strtol(tok, NULL, 0);
3161 minorVersion = strtol(tok, NULL, 0);
3169 patchVersion = strtol(tok, NULL, 0);
3177 tok = strtok_s(NULL,
".", &context);
3184 if (majorVersion < 5)
3186 if (minorVersion < 4)
3187 version = 0x10000000;
3189 version = 0x10010000;
3193 switch (majorVersion)
3196 version = 0x10010000;
3200 version = 0x10020000;
3204 version = 0x10030000;
3208 version = 0x10040000;
3212 version = 0x10050000;
3216 version = 0x10060000;
3220 version = 0x10070000;
3224 version = 0x10080000;
3228 version = 0x10090000;
3232 version = 0x10100000;
3236 version |= (minorVersion << 8) | (patchVersion);
3240 free(kernelVersion);
3249 PCSC_SCardEstablishContext,
3250 PCSC_SCardReleaseContext,
3251 PCSC_SCardIsValidContext,
3252 PCSC_SCardListReaderGroupsA,
3253 PCSC_SCardListReaderGroupsW,
3254 PCSC_SCardListReadersA,
3255 PCSC_SCardListReadersW,
3256 PCSC_SCardListCardsA,
3257 PCSC_SCardListCardsW,
3258 PCSC_SCardListInterfacesA,
3259 PCSC_SCardListInterfacesW,
3260 PCSC_SCardGetProviderIdA,
3261 PCSC_SCardGetProviderIdW,
3262 PCSC_SCardGetCardTypeProviderNameA,
3263 PCSC_SCardGetCardTypeProviderNameW,
3264 PCSC_SCardIntroduceReaderGroupA,
3265 PCSC_SCardIntroduceReaderGroupW,
3266 PCSC_SCardForgetReaderGroupA,
3267 PCSC_SCardForgetReaderGroupW,
3268 PCSC_SCardIntroduceReaderA,
3269 PCSC_SCardIntroduceReaderW,
3270 PCSC_SCardForgetReaderA,
3271 PCSC_SCardForgetReaderW,
3272 PCSC_SCardAddReaderToGroupA,
3273 PCSC_SCardAddReaderToGroupW,
3274 PCSC_SCardRemoveReaderFromGroupA,
3275 PCSC_SCardRemoveReaderFromGroupW,
3276 PCSC_SCardIntroduceCardTypeA,
3277 PCSC_SCardIntroduceCardTypeW,
3278 PCSC_SCardSetCardTypeProviderNameA,
3279 PCSC_SCardSetCardTypeProviderNameW,
3280 PCSC_SCardForgetCardTypeA,
3281 PCSC_SCardForgetCardTypeW,
3282 PCSC_SCardFreeMemory,
3283 PCSC_SCardAccessStartedEvent,
3284 PCSC_SCardReleaseStartedEvent,
3285 PCSC_SCardLocateCardsA,
3286 PCSC_SCardLocateCardsW,
3287 PCSC_SCardLocateCardsByATRA,
3288 PCSC_SCardLocateCardsByATRW,
3289 PCSC_SCardGetStatusChangeA,
3290 PCSC_SCardGetStatusChangeW,
3294 PCSC_SCardReconnect,
3295 PCSC_SCardDisconnect,
3296 PCSC_SCardBeginTransaction,
3297 PCSC_SCardEndTransaction,
3298 PCSC_SCardCancelTransaction,
3303 PCSC_SCardGetTransmitCount,
3305 PCSC_SCardGetAttrib,
3306 PCSC_SCardSetAttrib,
3307 PCSC_SCardUIDlgSelectCardA,
3308 PCSC_SCardUIDlgSelectCardW,
3309 PCSC_GetOpenCardNameA,
3310 PCSC_GetOpenCardNameW,
3311 PCSC_SCardDlgExtendedError,
3312 PCSC_SCardReadCacheA,
3313 PCSC_SCardReadCacheW,
3314 PCSC_SCardWriteCacheA,
3315 PCSC_SCardWriteCacheW,
3316 PCSC_SCardGetReaderIconA,
3317 PCSC_SCardGetReaderIconW,
3318 PCSC_SCardGetDeviceTypeIdA,
3319 PCSC_SCardGetDeviceTypeIdW,
3320 PCSC_SCardGetReaderDeviceInstanceIdA,
3321 PCSC_SCardGetReaderDeviceInstanceIdW,
3322 PCSC_SCardListReadersWithDeviceInstanceIdA,
3323 PCSC_SCardListReadersWithDeviceInstanceIdW,
3329 return &PCSC_SCardApiFunctionTable;
3332int PCSC_InitializeSCardApi(
void)
3335 SetEnvironmentVariableA(
"PCSCLITE_NO_BLOCKING",
"1");
3337 g_PCSCModule = LoadLibraryX(
"/System/Library/Frameworks/PCSC.framework/PCSC");
3338 OSXVersion = determineMacOSXVersion();
3340 if (OSXVersion == 0)
3344 g_PCSCModule = LoadLibraryA(
"libpcsclite.so.1");
3347 g_PCSCModule = LoadLibraryA(
"libpcsclite.so");
3356#undef SCardListReaderGroups
3357#undef SCardListReaders
3358#undef SCardListCards
3359#undef SCardListInterfaces
3360#undef SCardGetProviderId
3361#undef SCardGetCardTypeProviderName
3362#undef SCardIntroduceReaderGroup
3363#undef SCardForgetReaderGroup
3364#undef SCardIntroduceReader
3365#undef SCardForgetReader
3366#undef SCardAddReaderToGroup
3367#undef SCardRemoveReaderFromGroup
3368#undef SCardIntroduceCardType
3369#undef SCardSetCardTypeProviderName
3370#undef SCardForgetCardType
3371#undef SCardLocateCards
3372#undef SCardLocateCardsByATR
3373#undef SCardGetStatusChange
3376#undef SCardUIDlgSelectCard
3377#undef GetOpenCardName
3378#undef SCardReadCache
3379#undef SCardWriteCache
3380#undef SCardGetReaderIcon
3381#undef SCardGetDeviceTypeId
3382#undef SCardGetReaderDeviceInstanceId
3383#undef SCardListReadersWithDeviceInstanceId
3385 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardEstablishContext);
3386 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardReleaseContext);
3387 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardIsValidContext);
3388 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardConnect);
3389 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardReconnect);
3390 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardDisconnect);
3391 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardBeginTransaction);
3392 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardEndTransaction);
3393 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardStatus);
3394 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardGetStatusChange);
3398 if (OSXVersion >= 0x10050600)
3400 WINSCARD_LOAD_PROC_EX(g_PCSCModule, g_PCSC, SCardControl, SCardControl132);
3404 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardControl);
3407 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardControl);
3409 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardTransmit);
3410 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardListReaderGroups);
3411 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardListReaders);
3412 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardCancel);
3413 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardGetAttrib);
3414 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardSetAttrib);
3415 g_PCSC.pfnSCardFreeMemory = NULL;
3417 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardFreeMemory);
3420 if (g_PCSC.pfnSCardFreeMemory)
3421 g_SCardAutoAllocate = TRUE;
3423#ifdef DISABLE_PCSC_SCARD_AUTOALLOCATE
3424 g_PCSC.pfnSCardFreeMemory = NULL;
3425 g_SCardAutoAllocate = FALSE;
3428 g_PnP_Notification = FALSE;
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree