26#include <freerdp/config.h>
28#include <winpr/assert.h>
31#include <winpr/print.h>
32#include <winpr/stream.h>
33#include <winpr/library.h>
34#include <winpr/smartcard.h>
36#include <freerdp/freerdp.h>
37#include <freerdp/channels/rdpdr.h>
38#include <freerdp/channels/scard.h>
40#include <freerdp/utils/rdpdr_utils.h>
41#include <freerdp/utils/smartcard_pack.h>
42#include <freerdp/utils/smartcard_call.h>
44#include "smartcard_pack.h"
46#include <freerdp/log.h>
47#define SCARD_TAG FREERDP_TAG("utils.smartcard.call")
49#if defined(WITH_SMARTCARD_EMULATE)
50#include <freerdp/emulate/scard/smartcard_emulate.h>
57#define wrap_raw(ctx, fkt, ...) \
58 ((ctx)->useEmulatedCard ? Emulate_##fkt((ctx)->emulation, ##__VA_ARGS__) \
59 : (ctx)->pWinSCardApi->pfn##fkt(__VA_ARGS__))
60#define wrap_ptr(ctx, fkt, ...) wrap_raw(ctx, fkt, ##__VA_ARGS__)
62#define wrap_raw(ctx, fkt, ...) \
63 ((ctx)->useEmulatedCard ? SCARD_F_INTERNAL_ERROR : (ctx)->pWinSCardApi->pfn##fkt(__VA_ARGS__))
64#define wrap_ptr(ctx, fkt, ...) \
65 ((ctx)->useEmulatedCard ? nullptr : (ctx)->pWinSCardApi->pfn##fkt(__VA_ARGS__))
69#define wrap(ctx, fkt, ...) wrap_raw(ctx, fkt, ##__VA_ARGS__)
71#define wrap(ctx, fkt, ...) \
73 LONG defstatus = wrap_raw(ctx, fkt, ##__VA_ARGS__); \
74 if (defstatus != SCARD_S_SUCCESS) \
75 WLog_Print(ctx->log, WLOG_TRACE, "[" #fkt "] failed with %s", \
76 SCardGetErrorString(defstatus)); \
81struct s_scard_call_context
86 wHashTable* rgSCardContextList;
87#if defined(WITH_SMARTCARD_EMULATE)
88 SmartcardEmulationContext* emulation;
90 HANDLE hWinSCardLibrary;
96 void* (*fn_new)(
void*, SCARDCONTEXT);
97 void (*fn_free)(
void*);
102struct s_scard_context_element
105 void (*fn_free)(
void*);
108static void context_free(
void* arg);
110WINPR_ATTR_NODISCARD WINPR_ATTR_NODISCARD
static LONG
111smartcard_EstablishContext_Call(scard_call_context* smartcard,
wStream* out,
114 SCARDCONTEXT hContext = WINPR_C_ARRAY_INIT;
117 LONG status = ret.ReturnCode =
118 wrap(smartcard, SCardEstablishContext, call->dwScope,
nullptr,
nullptr, &hContext);
120 if (ret.ReturnCode == SCARD_S_SUCCESS)
122 const void* key = (
void*)(
size_t)hContext;
123 struct s_scard_context_element* pContext =
124 calloc(1,
sizeof(
struct s_scard_context_element));
126 return STATUS_NO_MEMORY;
128 pContext->fn_free = smartcard->fn_free;
130 if (smartcard->fn_new)
132 pContext->context = smartcard->fn_new(smartcard->userdata, hContext);
133 if (!pContext->context)
136 return STATUS_NO_MEMORY;
140 if (!HashTable_Insert(smartcard->rgSCardContextList, key, (
void*)pContext))
142 WLog_Print(smartcard->log, WLOG_ERROR,
"HashTable_Insert failed!");
143 context_free(pContext);
144 return STATUS_INTERNAL_ERROR;
149 return scard_log_status_error_wlog(smartcard->log,
"SCardEstablishContext", status);
153 smartcard_scard_context_native_to_redir(&(ret.hContext), hContext);
155 status = smartcard_pack_establish_context_return(out, &ret);
156 if (status != SCARD_S_SUCCESS)
158 return scard_log_status_error_wlog(smartcard->log,
159 "smartcard_pack_establish_context_return", status);
162 return ret.ReturnCode;
165WINPR_ATTR_NODISCARD
static LONG smartcard_ReleaseContext_Call(scard_call_context* smartcard,
166 WINPR_ATTR_UNUSED
wStream* out,
171 WINPR_ASSERT(smartcard);
173 WINPR_ASSERT(operation);
175 ret.ReturnCode = wrap(smartcard, SCardReleaseContext, operation->hContext);
177 if (ret.ReturnCode == SCARD_S_SUCCESS)
178 HashTable_Remove(smartcard->rgSCardContextList, (
void*)operation->hContext);
181 return scard_log_status_error_wlog(smartcard->log,
"SCardReleaseContext", ret.ReturnCode);
184 smartcard_trace_long_return_int(smartcard->log, &ret,
"ReleaseContext");
185 return ret.ReturnCode;
188WINPR_ATTR_NODISCARD
static LONG smartcard_IsValidContext_Call(scard_call_context* smartcard,
189 WINPR_ATTR_UNUSED
wStream* out,
194 WINPR_ASSERT(smartcard);
196 WINPR_ASSERT(operation);
198 ret.ReturnCode = wrap(smartcard, SCardIsValidContext, operation->hContext);
199 smartcard_trace_long_return_int(smartcard->log, &ret,
"IsValidContext");
200 return ret.ReturnCode;
203WINPR_ATTR_NODISCARD
static LONG smartcard_ListReaderGroupsA_Call(scard_call_context* smartcard,
209 LPSTR mszGroups =
nullptr;
212 WINPR_ASSERT(smartcard);
214 WINPR_ASSERT(operation);
216 cchGroups = SCARD_AUTOALLOCATE;
218 wrap(smartcard, SCardListReaderGroupsA, operation->hContext, (LPSTR)&mszGroups, &cchGroups);
219 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchGroups == SCARD_AUTOALLOCATE))
220 return SCARD_F_UNKNOWN_ERROR;
222 ret.msz = (BYTE*)mszGroups;
223 ret.cBytes = cchGroups;
225 status = smartcard_pack_list_reader_groups_return(out, &ret, FALSE);
227 if (status != SCARD_S_SUCCESS)
231 wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
233 return ret.ReturnCode;
236WINPR_ATTR_NODISCARD
static LONG smartcard_ListReaderGroupsW_Call(scard_call_context* smartcard,
242 LPWSTR mszGroups =
nullptr;
245 WINPR_ASSERT(smartcard);
247 WINPR_ASSERT(operation);
249 cchGroups = SCARD_AUTOALLOCATE;
250 status = ret.ReturnCode = wrap(smartcard, SCardListReaderGroupsW, operation->hContext,
251 (LPWSTR)&mszGroups, &cchGroups);
252 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchGroups == SCARD_AUTOALLOCATE))
253 return SCARD_F_UNKNOWN_ERROR;
255 ret.msz = (BYTE*)mszGroups;
257 WINPR_ASSERT(cchGroups < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
258 const size_t blen =
sizeof(WCHAR) * cchGroups;
259 WINPR_ASSERT(blen <= UINT32_MAX);
260 ret.cBytes = (UINT32)blen;
262 if (status != SCARD_S_SUCCESS)
265 status = smartcard_pack_list_reader_groups_return(out, &ret, TRUE);
267 if (status != SCARD_S_SUCCESS)
271 wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
273 return ret.ReturnCode;
277static BOOL filter_match(wLinkedList* list, LPCSTR reader,
size_t readerLen)
282 LinkedList_Enumerator_Reset(list);
284 while (LinkedList_Enumerator_MoveNext(list))
286 const char* filter = LinkedList_Enumerator_Current(list);
290 if (strstr(reader, filter) !=
nullptr)
299static DWORD filter_device_by_name_a(wLinkedList* list, LPSTR* mszReaders, DWORD cchReaders)
304 if (*mszReaders ==
nullptr || LinkedList_Count(list) < 1)
309 LPCSTR rreader = &(*mszReaders)[rpos];
310 LPSTR wreader = &(*mszReaders)[wpos];
311 size_t readerLen = strnlen(rreader, cchReaders - rpos);
313 rpos += readerLen + 1;
315 if (filter_match(list, rreader, readerLen))
317 if (rreader != wreader)
318 memmove(wreader, rreader, readerLen + 1);
320 wpos += readerLen + 1;
322 }
while (rpos < cchReaders);
327 if (wpos >= cchReaders)
330 (*mszReaders)[wpos++] =
'\0';
337static DWORD filter_device_by_name_w(wLinkedList* list, LPWSTR* mszReaders, DWORD cchReaders)
340 LPSTR readers =
nullptr;
342 if (LinkedList_Count(list) < 1)
345 readers = ConvertMszWCharNToUtf8Alloc(*mszReaders, cchReaders,
nullptr);
353 *mszReaders =
nullptr;
354 rc = filter_device_by_name_a(list, &readers, cchReaders);
356 *mszReaders = ConvertMszUtf8NToWCharAlloc(readers, rc,
nullptr);
364WINPR_ATTR_NODISCARD
static LONG smartcard_ListReadersA_Call(scard_call_context* smartcard,
369 LPSTR mszReaders =
nullptr;
371 WINPR_ASSERT(smartcard);
373 WINPR_ASSERT(operation);
376 DWORD cchReaders = SCARD_AUTOALLOCATE;
377 LONG status = ret.ReturnCode = wrap(smartcard, SCardListReadersA, operation->hContext,
378 (LPCSTR)call->mszGroups, (LPSTR)&mszReaders, &cchReaders);
379 if (status == SCARD_S_SUCCESS)
381 if (cchReaders == SCARD_AUTOALLOCATE)
382 status = SCARD_F_UNKNOWN_ERROR;
385 if (status != SCARD_S_SUCCESS)
387 (void)scard_log_status_error_wlog(smartcard->log,
"SCardListReadersA", status);
388 return smartcard_pack_list_readers_return(out, &ret, FALSE);
391 void* original = mszReaders;
392 cchReaders = filter_device_by_name_a(smartcard->names, &mszReaders, cchReaders);
393 ret.msz = (BYTE*)mszReaders;
394 ret.cBytes = cchReaders;
396 status = smartcard_pack_list_readers_return(out, &ret, FALSE);
398 wrap(smartcard, SCardFreeMemory, operation->hContext, original);
400 if (status != SCARD_S_SUCCESS)
401 return scard_log_status_error_wlog(smartcard->log,
"smartcard_pack_list_readers_return",
404 return ret.ReturnCode;
407WINPR_ATTR_NODISCARD
static LONG smartcard_ListReadersW_Call(scard_call_context* smartcard,
413 DWORD cchReaders = 0;
429 WINPR_ASSERT(smartcard);
430 WINPR_ASSERT(operation);
432 call = &operation->call.listReaders;
434 string.bp = call->mszGroups;
435 cchReaders = SCARD_AUTOALLOCATE;
436 status = ret.ReturnCode = wrap(smartcard, SCardListReadersW, operation->hContext,
string.wz,
437 (LPWSTR)&mszReaders.pw, &cchReaders);
438 if (status == SCARD_S_SUCCESS)
440 if (cchReaders == SCARD_AUTOALLOCATE)
441 status = SCARD_F_UNKNOWN_ERROR;
444 if (status != SCARD_S_SUCCESS)
446 (void)scard_log_status_error_wlog(smartcard->log,
"SCardListReadersW", status);
447 return smartcard_pack_list_readers_return(out, &ret, TRUE);
450 void* original = mszReaders.pb;
451 cchReaders = filter_device_by_name_w(smartcard->names, &mszReaders.pw, cchReaders);
452 ret.msz = mszReaders.pb;
453 ret.cBytes = cchReaders *
sizeof(WCHAR);
454 status = smartcard_pack_list_readers_return(out, &ret, TRUE);
457 wrap(smartcard, SCardFreeMemory, operation->hContext, original);
459 if (status != SCARD_S_SUCCESS)
462 return ret.ReturnCode;
465WINPR_ATTR_NODISCARD
static LONG
466smartcard_IntroduceReaderGroupA_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
472 WINPR_ASSERT(smartcard);
474 WINPR_ASSERT(operation);
476 call = &operation->call.contextAndStringA;
477 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupA, operation->hContext, call->sz);
478 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderGroupA", ret.ReturnCode);
479 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderGroupA");
480 return ret.ReturnCode;
483WINPR_ATTR_NODISCARD
static LONG
484smartcard_IntroduceReaderGroupW_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
490 WINPR_ASSERT(smartcard);
492 WINPR_ASSERT(operation);
494 call = &operation->call.contextAndStringW;
495 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupW, operation->hContext, call->sz);
496 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderGroupW", ret.ReturnCode);
497 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderGroupW");
498 return ret.ReturnCode;
501WINPR_ATTR_NODISCARD
static LONG smartcard_IntroduceReaderA_Call(scard_call_context* smartcard,
502 WINPR_ATTR_UNUSED
wStream* out,
508 WINPR_ASSERT(smartcard);
510 WINPR_ASSERT(operation);
512 call = &operation->call.contextAndTwoStringA;
514 wrap(smartcard, SCardIntroduceReaderA, operation->hContext, call->sz1, call->sz2);
515 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderA", ret.ReturnCode);
516 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderA");
517 return ret.ReturnCode;
520WINPR_ATTR_NODISCARD
static LONG smartcard_IntroduceReaderW_Call(scard_call_context* smartcard,
521 WINPR_ATTR_UNUSED
wStream* out,
527 WINPR_ASSERT(smartcard);
529 WINPR_ASSERT(operation);
531 call = &operation->call.contextAndTwoStringW;
533 wrap(smartcard, SCardIntroduceReaderW, operation->hContext, call->sz1, call->sz2);
534 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderW", ret.ReturnCode);
535 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderW");
536 return ret.ReturnCode;
539WINPR_ATTR_NODISCARD
static LONG smartcard_ForgetReaderA_Call(scard_call_context* smartcard,
540 WINPR_ATTR_UNUSED
wStream* out,
546 WINPR_ASSERT(smartcard);
548 WINPR_ASSERT(operation);
550 call = &operation->call.contextAndStringA;
551 ret.ReturnCode = wrap(smartcard, SCardForgetReaderA, operation->hContext, call->sz);
552 scard_log_status_error_wlog(smartcard->log,
"SCardForgetReaderA", ret.ReturnCode);
553 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardForgetReaderA");
554 return ret.ReturnCode;
557WINPR_ATTR_NODISCARD
static LONG smartcard_ForgetReaderW_Call(scard_call_context* smartcard,
558 WINPR_ATTR_UNUSED
wStream* out,
564 WINPR_ASSERT(smartcard);
566 WINPR_ASSERT(operation);
568 call = &operation->call.contextAndStringW;
569 ret.ReturnCode = wrap(smartcard, SCardForgetReaderW, operation->hContext, call->sz);
570 scard_log_status_error_wlog(smartcard->log,
"SCardForgetReaderW", ret.ReturnCode);
571 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardForgetReaderW");
572 return ret.ReturnCode;
575WINPR_ATTR_NODISCARD
static LONG smartcard_AddReaderToGroupA_Call(scard_call_context* smartcard,
576 WINPR_ATTR_UNUSED
wStream* out,
582 WINPR_ASSERT(smartcard);
584 WINPR_ASSERT(operation);
586 call = &operation->call.contextAndTwoStringA;
588 wrap(smartcard, SCardAddReaderToGroupA, operation->hContext, call->sz1, call->sz2);
589 scard_log_status_error_wlog(smartcard->log,
"SCardAddReaderToGroupA", ret.ReturnCode);
590 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardAddReaderToGroupA");
591 return ret.ReturnCode;
594WINPR_ATTR_NODISCARD
static LONG smartcard_AddReaderToGroupW_Call(scard_call_context* smartcard,
595 WINPR_ATTR_UNUSED
wStream* out,
601 WINPR_ASSERT(smartcard);
603 WINPR_ASSERT(operation);
605 call = &operation->call.contextAndTwoStringW;
607 wrap(smartcard, SCardAddReaderToGroupW, operation->hContext, call->sz1, call->sz2);
608 scard_log_status_error_wlog(smartcard->log,
"SCardAddReaderToGroupW", ret.ReturnCode);
609 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardAddReaderToGroupA");
610 return ret.ReturnCode;
613WINPR_ATTR_NODISCARD
static LONG
614smartcard_RemoveReaderFromGroupA_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
620 WINPR_ASSERT(smartcard);
622 WINPR_ASSERT(operation);
624 call = &operation->call.contextAndTwoStringA;
626 wrap(smartcard, SCardRemoveReaderFromGroupA, operation->hContext, call->sz1, call->sz2);
627 scard_log_status_error_wlog(smartcard->log,
"SCardRemoveReaderFromGroupA", ret.ReturnCode);
628 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardRemoveReaderFromGroupA");
629 return ret.ReturnCode;
632WINPR_ATTR_NODISCARD
static LONG
633smartcard_RemoveReaderFromGroupW_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
639 WINPR_ASSERT(smartcard);
641 WINPR_ASSERT(operation);
643 call = &operation->call.contextAndTwoStringW;
645 wrap(smartcard, SCardRemoveReaderFromGroupW, operation->hContext, call->sz1, call->sz2);
646 scard_log_status_error_wlog(smartcard->log,
"SCardRemoveReaderFromGroupW", ret.ReturnCode);
647 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardRemoveReaderFromGroupW");
648 return ret.ReturnCode;
651WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsA_Call(scard_call_context* smartcard,
659 WINPR_ASSERT(smartcard);
660 WINPR_ASSERT(operation);
662 call = &operation->call.locateCardsA;
664 ret.ReturnCode = wrap(smartcard, SCardLocateCardsA, operation->hContext, call->mszCards,
665 call->rgReaderStates, call->cReaders);
666 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsA", ret.ReturnCode);
667 ret.rgReaderStates =
nullptr;
669 if (call->cReaders > 0)
674 if (!ret.rgReaderStates)
675 return STATUS_NO_MEMORY;
676 ret.cReaders = call->cReaders;
679 for (UINT32 x = 0; x < ret.cReaders; x++)
684 cur->dwCurrentState = cstate->dwCurrentState;
685 cur->dwEventState = cstate->dwEventState;
686 cur->cbAtr = cstate->cbAtr;
687 CopyMemory(&(cur->rgbAtr), &(cstate->rgbAtr),
sizeof(cur->rgbAtr));
688 if (!smartcard_reader_state_return_is_valid(x, cur))
690 free(ret.rgReaderStates);
691 return SCARD_E_INVALID_ATR;
695 status = smartcard_pack_locate_cards_return(out, &ret);
696 free(ret.rgReaderStates);
698 if (status != SCARD_S_SUCCESS)
701 return ret.ReturnCode;
704WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsW_Call(scard_call_context* smartcard,
711 WINPR_ASSERT(smartcard);
712 WINPR_ASSERT(operation);
716 ret.ReturnCode = wrap(smartcard, SCardLocateCardsW, operation->hContext, call->mszCards,
717 call->rgReaderStates, call->cReaders);
718 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsW", ret.ReturnCode);
719 ret.rgReaderStates =
nullptr;
721 if (call->cReaders > 0)
726 if (!ret.rgReaderStates)
727 return STATUS_NO_MEMORY;
728 ret.cReaders = call->cReaders;
731 for (UINT32 x = 0; x < ret.cReaders; x++)
736 cur->dwCurrentState = cstate->dwCurrentState;
737 cur->dwEventState = cstate->dwEventState;
738 cur->cbAtr = cstate->cbAtr;
739 CopyMemory(&(cur->rgbAtr), &(cstate->rgbAtr),
sizeof(cur->rgbAtr));
740 if (!smartcard_reader_state_return_is_valid(x, cur))
742 free(ret.rgReaderStates);
743 return SCARD_E_INVALID_ATR;
747 status = smartcard_pack_locate_cards_return(out, &ret);
748 free(ret.rgReaderStates);
750 if (status != SCARD_S_SUCCESS)
753 return ret.ReturnCode;
756WINPR_ATTR_NODISCARD
static LONG smartcard_ReadCacheA_Call(scard_call_context* smartcard,
765 WINPR_ASSERT(smartcard);
767 WINPR_ASSERT(operation);
769 call = &operation->call.readCacheA;
770 autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE);
772 if (!call->Common.fPbDataIsNULL)
776 ret.pbData = calloc(1, call->Common.cbDataLen);
778 return SCARD_F_INTERNAL_ERROR;
780 ret.cbDataLen = call->Common.cbDataLen;
784 ret.ReturnCode = wrap(smartcard, SCardReadCacheA, operation->hContext,
785 call->Common.CardIdentifier, call->Common.FreshnessCounter,
786 call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
789 wrap(smartcard, SCardReadCacheA, operation->hContext, call->Common.CardIdentifier,
790 call->Common.FreshnessCounter, call->szLookupName, ret.pbData, &ret.cbDataLen);
792 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, call->szLookupName,
795 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
796 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
798 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheA", ret.ReturnCode);
801 status = smartcard_pack_read_cache_return(out, &ret);
803 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
806 if (status != SCARD_S_SUCCESS)
809 return ret.ReturnCode;
812WINPR_ATTR_NODISCARD
static LONG smartcard_ReadCacheW_Call(scard_call_context* smartcard,
820 WINPR_ASSERT(smartcard);
822 WINPR_ASSERT(operation);
824 call = &operation->call.readCacheW;
826 if (!call->Common.fPbDataIsNULL)
827 ret.cbDataLen = SCARD_AUTOALLOCATE;
830 wrap(smartcard, SCardReadCacheW, operation->hContext, call->Common.CardIdentifier,
831 call->Common.FreshnessCounter, call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
833 if (WLog_IsLevelActive(smartcard->log, WLOG_TRACE))
835 char buffer[128] = WINPR_C_ARRAY_INIT;
836 (void)ConvertWCharToUtf8(call->szLookupName, buffer,
sizeof(buffer));
837 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, buffer, ret.cbDataLen);
839 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
840 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
842 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheW", ret.ReturnCode);
845 status = smartcard_pack_read_cache_return(out, &ret);
847 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
849 if (status != SCARD_S_SUCCESS)
852 return ret.ReturnCode;
855WINPR_ATTR_NODISCARD
static LONG smartcard_WriteCacheA_Call(scard_call_context* smartcard,
856 WINPR_ATTR_UNUSED
wStream* out,
862 WINPR_ASSERT(smartcard);
864 WINPR_ASSERT(operation);
866 call = &operation->call.writeCacheA;
868 ret.ReturnCode = wrap(smartcard, SCardWriteCacheA, operation->hContext,
869 call->Common.CardIdentifier, call->Common.FreshnessCounter,
870 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
871 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheA", ret.ReturnCode);
872 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheA");
873 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, call->szLookupName,
874 call->Common.cbDataLen);
875 return ret.ReturnCode;
878WINPR_ATTR_NODISCARD
static LONG smartcard_WriteCacheW_Call(scard_call_context* smartcard,
879 WINPR_ATTR_UNUSED
wStream* out,
885 WINPR_ASSERT(smartcard);
887 WINPR_ASSERT(operation);
889 call = &operation->call.writeCacheW;
891 ret.ReturnCode = wrap(smartcard, SCardWriteCacheW, operation->hContext,
892 call->Common.CardIdentifier, call->Common.FreshnessCounter,
893 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
894 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheW", ret.ReturnCode);
895 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheW");
897 if (WLog_IsLevelActive(smartcard->log, WLOG_TRACE))
899 char buffer[128] = WINPR_C_ARRAY_INIT;
900 (void)ConvertWCharToUtf8(call->szLookupName, buffer,
sizeof(buffer));
901 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, buffer,
902 call->Common.cbDataLen);
904 return ret.ReturnCode;
907WINPR_ATTR_NODISCARD
static LONG smartcard_GetTransmitCount_Call(scard_call_context* smartcard,
914 WINPR_ASSERT(smartcard);
916 WINPR_ASSERT(operation);
918 ret.ReturnCode = wrap(smartcard, SCardGetTransmitCount, operation->hCard, &ret.cTransmitCount);
919 scard_log_status_error_wlog(smartcard->log,
"SCardGetTransmitCount", ret.ReturnCode);
920 status = smartcard_pack_get_transmit_count_return(out, &ret);
921 if (status != SCARD_S_SUCCESS)
924 return ret.ReturnCode;
927WINPR_ATTR_NODISCARD
static LONG smartcard_ReleaseStartedEvent_Call(scard_call_context* smartcard,
931 WINPR_UNUSED(smartcard);
933 WINPR_UNUSED(operation);
935 WLog_Print(smartcard->log, WLOG_WARN,
936 "According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
937 "this is not supported?!?");
938 return SCARD_E_UNSUPPORTED_FEATURE;
941WINPR_ATTR_NODISCARD
static LONG smartcard_GetReaderIcon_Call(scard_call_context* smartcard,
949 WINPR_ASSERT(smartcard);
951 WINPR_ASSERT(operation);
953 call = &operation->call.getReaderIcon;
955 ret.cbDataLen = SCARD_AUTOALLOCATE;
956 ret.ReturnCode = wrap(smartcard, SCardGetReaderIconW, operation->hContext, call->szReaderName,
957 (LPBYTE)&ret.pbData, &ret.cbDataLen);
958 scard_log_status_error_wlog(smartcard->log,
"SCardGetReaderIconW", ret.ReturnCode);
959 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cbDataLen == SCARD_AUTOALLOCATE))
960 return SCARD_F_UNKNOWN_ERROR;
962 status = smartcard_pack_get_reader_icon_return(out, &ret);
963 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
964 if (status != SCARD_S_SUCCESS)
967 return ret.ReturnCode;
970WINPR_ATTR_NODISCARD
static LONG smartcard_GetDeviceTypeId_Call(scard_call_context* smartcard,
978 WINPR_ASSERT(smartcard);
980 WINPR_ASSERT(operation);
982 call = &operation->call.getDeviceTypeId;
984 ret.ReturnCode = wrap(smartcard, SCardGetDeviceTypeIdW, operation->hContext, call->szReaderName,
986 scard_log_status_error_wlog(smartcard->log,
"SCardGetDeviceTypeIdW", ret.ReturnCode);
988 status = smartcard_pack_device_type_id_return(out, &ret);
989 if (status != SCARD_S_SUCCESS)
992 return ret.ReturnCode;
996static BOOL smartcard_context_was_aborted(scard_call_context* smartcard)
998 WINPR_ASSERT(smartcard);
1000 HANDLE handles[] = { smartcard->stopEvent, freerdp_abort_event(smartcard->context) };
1001 const DWORD rc = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, 0);
1002 return (rc >= WAIT_OBJECT_0) && (rc <= WAIT_OBJECT_0 + ARRAYSIZE(handles));
1005WINPR_ATTR_NODISCARD
static LONG smartcard_GetStatusChangeA_Call(scard_call_context* smartcard,
1009 LONG status = STATUS_NO_MEMORY;
1010 DWORD dwTimeOut = 0;
1011 const DWORD dwTimeStep = 100;
1016 WINPR_ASSERT(smartcard);
1018 WINPR_ASSERT(operation);
1020 call = &operation->call.getStatusChangeA;
1021 dwTimeOut = call->dwTimeOut;
1023 if (call->cReaders > 0)
1026 ret.rgReaderStates =
1028 if (!rgReaderStates || !ret.rgReaderStates)
1031 ret.cReaders = call->cReaders;
1034 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
1036 if (call->cReaders > 0)
1037 memcpy(rgReaderStates, call->rgReaderStates,
1039 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1040 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
1041 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1043 if (smartcard_context_was_aborted(smartcard))
1045 if (dwTimeOut != INFINITE)
1048 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", ret.ReturnCode);
1050 status = SCARD_E_INVALID_ATR;
1051 for (UINT32 index = 0; index < ret.cReaders; index++)
1056 rout->dwCurrentState = cur->dwCurrentState;
1057 rout->dwEventState = cur->dwEventState;
1058 rout->cbAtr = cur->cbAtr;
1059 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1060 if (!smartcard_reader_state_return_is_valid(index, rout))
1064 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1066 free(ret.rgReaderStates);
1067 free(rgReaderStates);
1068 if (status != SCARD_S_SUCCESS)
1070 return ret.ReturnCode;
1073WINPR_ATTR_NODISCARD
static LONG smartcard_GetStatusChangeW_Call(scard_call_context* smartcard,
1077 LONG status = STATUS_NO_MEMORY;
1078 DWORD dwTimeOut = 0;
1079 const DWORD dwTimeStep = 100;
1083 WINPR_ASSERT(smartcard);
1085 WINPR_ASSERT(operation);
1088 dwTimeOut = call->dwTimeOut;
1090 if (call->cReaders > 0)
1093 ret.rgReaderStates =
1095 if (!rgReaderStates || !ret.rgReaderStates)
1098 ret.cReaders = call->cReaders;
1101 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
1103 if (call->cReaders > 0)
1104 memcpy(rgReaderStates, call->rgReaderStates,
1107 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
1108 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
1110 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1112 if (smartcard_context_was_aborted(smartcard))
1114 if (dwTimeOut != INFINITE)
1117 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeW", ret.ReturnCode);
1119 status = SCARD_E_INVALID_ATR;
1120 for (UINT32 index = 0; index < ret.cReaders; index++)
1125 rout->dwCurrentState = cur->dwCurrentState;
1126 rout->dwEventState = cur->dwEventState;
1127 rout->cbAtr = cur->cbAtr;
1128 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1129 if (!smartcard_reader_state_return_is_valid(index, rout))
1133 status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
1135 free(ret.rgReaderStates);
1136 free(rgReaderStates);
1137 if (status != SCARD_S_SUCCESS)
1139 return ret.ReturnCode;
1142WINPR_ATTR_NODISCARD
static LONG smartcard_Cancel_Call(scard_call_context* smartcard,
1143 WINPR_ATTR_UNUSED
wStream* out,
1148 WINPR_ASSERT(smartcard);
1150 WINPR_ASSERT(operation);
1152 ret.ReturnCode = wrap(smartcard, SCardCancel, operation->hContext);
1153 scard_log_status_error_wlog(smartcard->log,
"SCardCancel", ret.ReturnCode);
1154 smartcard_trace_long_return_int(smartcard->log, &ret,
"Cancel");
1155 return ret.ReturnCode;
1158WINPR_ATTR_NODISCARD
static LONG
1162 SCARDHANDLE hCard = 0;
1166 WINPR_ASSERT(smartcard);
1168 WINPR_ASSERT(operation);
1170 call = &operation->call.connectA;
1172 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1173 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1175 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1178 ret.ReturnCode = wrap(smartcard, SCardConnectA, operation->hContext, (
char*)call->szReader,
1179 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1180 &ret.dwActiveProtocol);
1181 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1182 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1184 status = smartcard_pack_connect_return(out, &ret);
1185 if (status != SCARD_S_SUCCESS)
1188 status = ret.ReturnCode;
1194WINPR_ATTR_NODISCARD
static LONG
1198 SCARDHANDLE hCard = 0;
1202 WINPR_ASSERT(smartcard);
1204 WINPR_ASSERT(operation);
1206 call = &operation->call.connectW;
1208 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1209 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1211 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1214 ret.ReturnCode = wrap(smartcard, SCardConnectW, operation->hContext, (WCHAR*)call->szReader,
1215 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1216 &ret.dwActiveProtocol);
1217 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1218 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1220 status = smartcard_pack_connect_return(out, &ret);
1221 if (status != SCARD_S_SUCCESS)
1224 status = ret.ReturnCode;
1230WINPR_ATTR_NODISCARD
static LONG smartcard_Reconnect_Call(scard_call_context* smartcard,
1238 WINPR_ASSERT(smartcard);
1240 WINPR_ASSERT(operation);
1242 call = &operation->call.reconnect;
1244 wrap(smartcard, SCardReconnect, operation->hCard, call->dwShareMode,
1245 call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
1246 scard_log_status_error_wlog(smartcard->log,
"SCardReconnect", ret.ReturnCode);
1247 status = smartcard_pack_reconnect_return(out, &ret);
1248 if (status != SCARD_S_SUCCESS)
1251 return ret.ReturnCode;
1254WINPR_ATTR_NODISCARD
static LONG smartcard_Disconnect_Call(scard_call_context* smartcard,
1255 WINPR_ATTR_UNUSED
wStream* out,
1261 WINPR_ASSERT(smartcard);
1263 WINPR_ASSERT(operation);
1265 call = &operation->call.hCardAndDisposition;
1267 ret.ReturnCode = wrap(smartcard, SCardDisconnect, operation->hCard, call->dwDisposition);
1268 scard_log_status_error_wlog(smartcard->log,
"SCardDisconnect", ret.ReturnCode);
1269 smartcard_trace_long_return_int(smartcard->log, &ret,
"Disconnect");
1271 return ret.ReturnCode;
1274WINPR_ATTR_NODISCARD
static LONG smartcard_BeginTransaction_Call(scard_call_context* smartcard,
1275 WINPR_ATTR_UNUSED
wStream* out,
1280 WINPR_ASSERT(smartcard);
1282 WINPR_ASSERT(operation);
1284 ret.ReturnCode = wrap(smartcard, SCardBeginTransaction, operation->hCard);
1285 scard_log_status_error_wlog(smartcard->log,
"SCardBeginTransaction", ret.ReturnCode);
1286 smartcard_trace_long_return_int(smartcard->log, &ret,
"BeginTransaction");
1287 return ret.ReturnCode;
1290WINPR_ATTR_NODISCARD
static LONG smartcard_EndTransaction_Call(scard_call_context* smartcard,
1291 WINPR_ATTR_UNUSED
wStream* out,
1297 WINPR_ASSERT(smartcard);
1299 WINPR_ASSERT(operation);
1301 call = &operation->call.hCardAndDisposition;
1303 ret.ReturnCode = wrap(smartcard, SCardEndTransaction, operation->hCard, call->dwDisposition);
1304 scard_log_status_error_wlog(smartcard->log,
"SCardEndTransaction", ret.ReturnCode);
1305 smartcard_trace_long_return_int(smartcard->log, &ret,
"EndTransaction");
1306 return ret.ReturnCode;
1309WINPR_ATTR_NODISCARD
static LONG smartcard_State_Call(scard_call_context* smartcard,
wStream* out,
1315 WINPR_ASSERT(smartcard);
1317 WINPR_ASSERT(operation);
1319 ret.cbAtrLen = SCARD_ATR_LENGTH;
1320 ret.ReturnCode = wrap(smartcard, SCardState, operation->hCard, &ret.dwState, &ret.dwProtocol,
1321 (BYTE*)&ret.rgAtr, &ret.cbAtrLen);
1323 scard_log_status_error_wlog(smartcard->log,
"SCardState", ret.ReturnCode);
1324 status = smartcard_pack_state_return(out, &ret);
1325 if (status != SCARD_S_SUCCESS)
1328 return ret.ReturnCode;
1331WINPR_ATTR_NODISCARD
static LONG smartcard_StatusA_Call(scard_call_context* smartcard,
wStream* out,
1336 DWORD cchReaderLen = 0;
1338 LPSTR mszReaderNames =
nullptr;
1341 WINPR_ASSERT(smartcard);
1343 WINPR_ASSERT(operation);
1345 call = &operation->call.status;
1347 call->cbAtrLen = 32;
1348 cbAtrLen = call->cbAtrLen;
1350 if (call->fmszReaderNamesIsNULL)
1353 cchReaderLen = SCARD_AUTOALLOCATE;
1355 status = ret.ReturnCode =
1356 wrap(smartcard, SCardStatusA, operation->hCard,
1357 call->fmszReaderNamesIsNULL ?
nullptr : (LPSTR)&mszReaderNames, &cchReaderLen,
1358 &ret.dwState, &ret.dwProtocol, cbAtrLen ? (BYTE*)&ret.pbAtr : nullptr, &cbAtrLen);
1360 scard_log_status_error_wlog(smartcard->log,
"SCardStatusA", status);
1361 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchReaderLen == SCARD_AUTOALLOCATE))
1362 return SCARD_F_UNKNOWN_ERROR;
1364 if (status == SCARD_S_SUCCESS)
1366 if (!call->fmszReaderNamesIsNULL)
1367 ret.mszReaderNames = (BYTE*)mszReaderNames;
1369 ret.cBytes = cchReaderLen;
1372 ret.cbAtrLen = cbAtrLen;
1375 status = smartcard_pack_status_return(out, &ret, FALSE);
1378 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1380 if (status != SCARD_S_SUCCESS)
1382 return ret.ReturnCode;
1385WINPR_ATTR_NODISCARD
static LONG smartcard_StatusW_Call(scard_call_context* smartcard,
wStream* out,
1390 LPWSTR mszReaderNames =
nullptr;
1394 WINPR_ASSERT(smartcard);
1396 WINPR_ASSERT(operation);
1398 call = &operation->call.status;
1404 cbAtrLen = call->cbAtrLen = 32;
1406 if (call->fmszReaderNamesIsNULL)
1409 ret.cBytes = SCARD_AUTOALLOCATE;
1411 status = ret.ReturnCode =
1412 wrap(smartcard, SCardStatusW, operation->hCard,
1413 call->fmszReaderNamesIsNULL ?
nullptr : (LPWSTR)&mszReaderNames, &ret.cBytes,
1414 &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
1415 scard_log_status_error_wlog(smartcard->log,
"SCardStatusW", status);
1416 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cBytes == SCARD_AUTOALLOCATE))
1417 return SCARD_F_UNKNOWN_ERROR;
1420 if (status == SCARD_S_SUCCESS)
1422 if (!call->fmszReaderNamesIsNULL)
1423 ret.mszReaderNames = (BYTE*)mszReaderNames;
1425 ret.cbAtrLen = cbAtrLen;
1428 if (ret.cBytes != SCARD_AUTOALLOCATE)
1431 WINPR_ASSERT(ret.cBytes < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
1432 blen =
sizeof(WCHAR) * ret.cBytes;
1433 WINPR_ASSERT(blen <= UINT32_MAX);
1434 ret.cBytes = (UINT32)blen;
1437 status = smartcard_pack_status_return(out, &ret, TRUE);
1438 if (status != SCARD_S_SUCCESS)
1442 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1444 return ret.ReturnCode;
1447WINPR_ATTR_NODISCARD
static LONG
1454 WINPR_ASSERT(smartcard);
1456 WINPR_ASSERT(operation);
1458 call = &operation->call.transmit;
1459 ret.cbRecvLength = 0;
1460 ret.pbRecvBuffer =
nullptr;
1462 if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
1464 if (call->cbRecvLength >= 66560)
1465 call->cbRecvLength = 66560;
1467 const UINT32 cbRecvLength = call->cbRecvLength;
1468 ret.pbRecvBuffer = (BYTE*)calloc(1, cbRecvLength);
1470 if (!ret.pbRecvBuffer)
1471 return STATUS_NO_MEMORY;
1472 ret.cbRecvLength = cbRecvLength;
1475 ret.pioRecvPci = call->pioRecvPci;
1477 wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
1478 call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
1480 scard_log_status_error_wlog(smartcard->log,
"SCardTransmit", ret.ReturnCode);
1482 status = smartcard_pack_transmit_return(out, &ret);
1483 free(ret.pbRecvBuffer);
1485 if (status != SCARD_S_SUCCESS)
1487 return ret.ReturnCode;
1490WINPR_ATTR_NODISCARD
static LONG smartcard_Control_Call(scard_call_context* smartcard,
wStream* out,
1497 WINPR_ASSERT(smartcard);
1499 WINPR_ASSERT(operation);
1501 call = &operation->call.control;
1502 ret.pvOutBuffer = (BYTE*)calloc(1, call->cbOutBufferSize);
1504 if (!ret.pvOutBuffer)
1505 return SCARD_E_NO_MEMORY;
1506 ret.cbOutBufferSize = call->cbOutBufferSize;
1509 wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
1510 call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
1511 scard_log_status_error_wlog(smartcard->log,
"SCardControl", ret.ReturnCode);
1512 status = smartcard_pack_control_return(out, &ret);
1514 free(ret.pvOutBuffer);
1515 if (status != SCARD_S_SUCCESS)
1517 return ret.ReturnCode;
1520WINPR_ATTR_NODISCARD
static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard,
1524 BOOL autoAllocate = FALSE;
1526 DWORD cbAttrLen = 0;
1527 LPBYTE pbAttr =
nullptr;
1531 WINPR_ASSERT(smartcard);
1532 WINPR_ASSERT(operation);
1534 call = &operation->call.getAttrib;
1536 if (!call->fpbAttrIsNULL)
1538 autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE);
1539 cbAttrLen = call->cbAttrLen;
1540 if (cbAttrLen && !autoAllocate)
1542 ret.pbAttr = (BYTE*)calloc(1, cbAttrLen);
1545 return SCARD_E_NO_MEMORY;
1548 pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
1552 wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
1553 scard_log_status_error_wlog(smartcard->log,
"SCardGetAttrib", ret.ReturnCode);
1554 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cbAttrLen == SCARD_AUTOALLOCATE))
1555 return SCARD_F_UNKNOWN_ERROR;
1557 ret.cbAttrLen = cbAttrLen;
1559 status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
1562 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
1568WINPR_ATTR_NODISCARD
static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard,
1569 WINPR_ATTR_UNUSED
wStream* out,
1575 WINPR_ASSERT(smartcard);
1577 WINPR_ASSERT(operation);
1579 call = &operation->call.setAttrib;
1581 ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
1583 scard_log_status_error_wlog(smartcard->log,
"SCardSetAttrib", ret.ReturnCode);
1584 smartcard_trace_long_return_int(smartcard->log, &ret,
"SetAttrib");
1586 return ret.ReturnCode;
1589WINPR_ATTR_NODISCARD
static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard,
1590 WINPR_ATTR_UNUSED
wStream* out,
1593 LONG status = SCARD_S_SUCCESS;
1595 WINPR_ASSERT(smartcard);
1597 WINPR_UNUSED(operation);
1599 if (!smartcard->StartedEvent)
1600 smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
1602 if (!smartcard->StartedEvent)
1603 status = SCARD_E_NO_SERVICE;
1608WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard,
1612 LONG status = SCARD_E_INVALID_HANDLE;
1615 WINPR_ASSERT(smartcard);
1616 WINPR_ASSERT(operation);
1623 return STATUS_NO_MEMORY;
1625 for (UINT32 i = 0; i < call->cReaders; i++)
1630 state->szReader = cstate->szReader;
1631 state->dwCurrentState = cstate->dwCurrentState;
1632 state->dwEventState = cstate->dwEventState;
1633 state->cbAtr = cstate->cbAtr;
1635 if (state->cbAtr >
sizeof(state->rgbAtr))
1637 WLog_WARN(SCARD_TAG,
"[%" PRIu32
"] val->cbAtr=%" PRIu32
", max=%" PRIuz, i,
1638 state->cbAtr,
sizeof(state->rgbAtr));
1641 CopyMemory(&(state->rgbAtr), &(cstate->rgbAtr),
sizeof(cstate->rgbAtr));
1644 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1645 0x000001F4, states, call->cReaders);
1647 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", status);
1648 for (UINT32 i = 0; i < call->cAtrs; i++)
1650 for (UINT32 j = 0; j < call->cReaders; j++)
1653 for (UINT32 k = 0; k < mask->cbAtr; k++)
1655 if ((mask->rgbAtr[k] & mask->rgbMask[k]) !=
1656 (states[j].rgbAtr[k] & mask->rgbMask[k]))
1661 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1666 ret.rgReaderStates =
nullptr;
1668 if (call->cReaders > 0)
1669 ret.rgReaderStates =
1672 if (!ret.rgReaderStates)
1674 status = STATUS_NO_MEMORY;
1678 ret.cReaders = call->cReaders;
1680 status = SCARD_E_INVALID_ATR;
1681 for (UINT32 i = 0; i < ret.cReaders; i++)
1686 cur->dwCurrentState = state->dwCurrentState;
1687 cur->dwEventState = state->dwEventState;
1688 cur->cbAtr = state->cbAtr;
1689 CopyMemory(&(cur->rgbAtr), &(state->rgbAtr),
sizeof(cur->rgbAtr));
1691 if (!smartcard_reader_state_return_is_valid(i, cur))
1695 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1699 free(ret.rgReaderStates);
1700 if (status != SCARD_S_SUCCESS)
1702 return ret.ReturnCode;
1705WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsByATRW_Call(scard_call_context* smartcard,
1709 LONG status = SCARD_E_INVALID_HANDLE;
1712 WINPR_ASSERT(smartcard);
1713 WINPR_ASSERT(operation);
1720 return STATUS_NO_MEMORY;
1722 for (UINT32 i = 0; i < call->cReaders; i++)
1727 state->szReader = cstate->szReader;
1728 state->dwCurrentState = cstate->dwCurrentState;
1729 state->dwEventState = cstate->dwEventState;
1730 state->cbAtr = cstate->cbAtr;
1732 if (state->cbAtr >
sizeof(state->rgbAtr))
1734 WLog_WARN(SCARD_TAG,
"[%" PRIu32
"] val->cbAtr=%" PRIu32
", max=%" PRIuz, i,
1735 state->cbAtr,
sizeof(state->rgbAtr));
1738 CopyMemory(&(state->rgbAtr), &(cstate->rgbAtr),
sizeof(cstate->rgbAtr));
1741 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
1742 0x000001F4, states, call->cReaders);
1744 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeW", status);
1745 for (UINT32 i = 0; i < call->cAtrs; i++)
1747 for (UINT32 j = 0; j < call->cReaders; j++)
1750 for (UINT32 k = 0; k < mask->cbAtr; k++)
1752 if ((mask->rgbAtr[k] & mask->rgbMask[k]) !=
1753 (states[j].rgbAtr[k] & mask->rgbMask[k]))
1758 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1763 ret.rgReaderStates =
nullptr;
1765 if (call->cReaders > 0)
1766 ret.rgReaderStates =
1769 if (!ret.rgReaderStates)
1771 status = STATUS_NO_MEMORY;
1775 ret.cReaders = call->cReaders;
1777 status = SCARD_E_INVALID_ATR;
1778 for (UINT32 i = 0; i < ret.cReaders; i++)
1783 cur->dwCurrentState = state->dwCurrentState;
1784 cur->dwEventState = state->dwEventState;
1785 cur->cbAtr = state->cbAtr;
1786 CopyMemory(&(cur->rgbAtr), &(state->rgbAtr),
sizeof(cur->rgbAtr));
1788 if (!smartcard_reader_state_return_is_valid(i, cur))
1792 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1796 free(ret.rgReaderStates);
1797 if (status != SCARD_S_SUCCESS)
1799 return ret.ReturnCode;
1802LONG smartcard_irp_device_control_call(scard_call_context* ctx,
wStream* out, NTSTATUS* pIoStatus,
1807 size_t objectBufferLength = 0;
1811 WINPR_ASSERT(pIoStatus);
1812 WINPR_ASSERT(operation);
1814 const UINT32 ioControlCode = operation->ioControlCode;
1822 const size_t outMaxLen = MAX(2048, operation->outputBufferLength);
1823 if (!Stream_EnsureRemainingCapacity(out, outMaxLen))
1824 return SCARD_E_NO_MEMORY;
1827 Stream_Write_UINT32(out, 0);
1828 Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH);
1829 Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH);
1830 Stream_Write_UINT32(out, 0);
1833 switch (ioControlCode)
1835 case SCARD_IOCTL_ESTABLISHCONTEXT:
1836 result = smartcard_EstablishContext_Call(ctx, out, operation);
1839 case SCARD_IOCTL_RELEASECONTEXT:
1840 result = smartcard_ReleaseContext_Call(ctx, out, operation);
1843 case SCARD_IOCTL_ISVALIDCONTEXT:
1844 result = smartcard_IsValidContext_Call(ctx, out, operation);
1847 case SCARD_IOCTL_LISTREADERGROUPSA:
1848 result = smartcard_ListReaderGroupsA_Call(ctx, out, operation);
1851 case SCARD_IOCTL_LISTREADERGROUPSW:
1852 result = smartcard_ListReaderGroupsW_Call(ctx, out, operation);
1855 case SCARD_IOCTL_LISTREADERSA:
1856 result = smartcard_ListReadersA_Call(ctx, out, operation);
1859 case SCARD_IOCTL_LISTREADERSW:
1860 result = smartcard_ListReadersW_Call(ctx, out, operation);
1863 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1864 result = smartcard_IntroduceReaderGroupA_Call(ctx, out, operation);
1867 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1868 result = smartcard_IntroduceReaderGroupW_Call(ctx, out, operation);
1871 case SCARD_IOCTL_FORGETREADERGROUPA:
1872 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
1875 case SCARD_IOCTL_FORGETREADERGROUPW:
1876 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
1879 case SCARD_IOCTL_INTRODUCEREADERA:
1880 result = smartcard_IntroduceReaderA_Call(ctx, out, operation);
1883 case SCARD_IOCTL_INTRODUCEREADERW:
1884 result = smartcard_IntroduceReaderW_Call(ctx, out, operation);
1887 case SCARD_IOCTL_FORGETREADERA:
1888 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
1891 case SCARD_IOCTL_FORGETREADERW:
1892 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
1895 case SCARD_IOCTL_ADDREADERTOGROUPA:
1896 result = smartcard_AddReaderToGroupA_Call(ctx, out, operation);
1899 case SCARD_IOCTL_ADDREADERTOGROUPW:
1900 result = smartcard_AddReaderToGroupW_Call(ctx, out, operation);
1903 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1904 result = smartcard_RemoveReaderFromGroupA_Call(ctx, out, operation);
1907 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1908 result = smartcard_RemoveReaderFromGroupW_Call(ctx, out, operation);
1911 case SCARD_IOCTL_LOCATECARDSA:
1912 result = smartcard_LocateCardsA_Call(ctx, out, operation);
1915 case SCARD_IOCTL_LOCATECARDSW:
1916 result = smartcard_LocateCardsW_Call(ctx, out, operation);
1919 case SCARD_IOCTL_GETSTATUSCHANGEA:
1920 result = smartcard_GetStatusChangeA_Call(ctx, out, operation);
1923 case SCARD_IOCTL_GETSTATUSCHANGEW:
1924 result = smartcard_GetStatusChangeW_Call(ctx, out, operation);
1927 case SCARD_IOCTL_CANCEL:
1928 result = smartcard_Cancel_Call(ctx, out, operation);
1931 case SCARD_IOCTL_CONNECTA:
1932 result = smartcard_ConnectA_Call(ctx, out, operation);
1935 case SCARD_IOCTL_CONNECTW:
1936 result = smartcard_ConnectW_Call(ctx, out, operation);
1939 case SCARD_IOCTL_RECONNECT:
1940 result = smartcard_Reconnect_Call(ctx, out, operation);
1943 case SCARD_IOCTL_DISCONNECT:
1944 result = smartcard_Disconnect_Call(ctx, out, operation);
1947 case SCARD_IOCTL_BEGINTRANSACTION:
1948 result = smartcard_BeginTransaction_Call(ctx, out, operation);
1951 case SCARD_IOCTL_ENDTRANSACTION:
1952 result = smartcard_EndTransaction_Call(ctx, out, operation);
1955 case SCARD_IOCTL_STATE:
1956 result = smartcard_State_Call(ctx, out, operation);
1959 case SCARD_IOCTL_STATUSA:
1960 result = smartcard_StatusA_Call(ctx, out, operation);
1963 case SCARD_IOCTL_STATUSW:
1964 result = smartcard_StatusW_Call(ctx, out, operation);
1967 case SCARD_IOCTL_TRANSMIT:
1968 result = smartcard_Transmit_Call(ctx, out, operation);
1971 case SCARD_IOCTL_CONTROL:
1972 result = smartcard_Control_Call(ctx, out, operation);
1975 case SCARD_IOCTL_GETATTRIB:
1976 result = smartcard_GetAttrib_Call(ctx, out, operation);
1979 case SCARD_IOCTL_SETATTRIB:
1980 result = smartcard_SetAttrib_Call(ctx, out, operation);
1983 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
1984 result = smartcard_AccessStartedEvent_Call(ctx, out, operation);
1987 case SCARD_IOCTL_LOCATECARDSBYATRA:
1988 result = smartcard_LocateCardsByATRA_Call(ctx, out, operation);
1991 case SCARD_IOCTL_LOCATECARDSBYATRW:
1992 result = smartcard_LocateCardsByATRW_Call(ctx, out, operation);
1995 case SCARD_IOCTL_READCACHEA:
1996 result = smartcard_ReadCacheA_Call(ctx, out, operation);
1999 case SCARD_IOCTL_READCACHEW:
2000 result = smartcard_ReadCacheW_Call(ctx, out, operation);
2003 case SCARD_IOCTL_WRITECACHEA:
2004 result = smartcard_WriteCacheA_Call(ctx, out, operation);
2007 case SCARD_IOCTL_WRITECACHEW:
2008 result = smartcard_WriteCacheW_Call(ctx, out, operation);
2011 case SCARD_IOCTL_GETTRANSMITCOUNT:
2012 result = smartcard_GetTransmitCount_Call(ctx, out, operation);
2015 case SCARD_IOCTL_RELEASETARTEDEVENT:
2016 result = smartcard_ReleaseStartedEvent_Call(ctx, out, operation);
2019 case SCARD_IOCTL_GETREADERICON:
2020 result = smartcard_GetReaderIcon_Call(ctx, out, operation);
2023 case SCARD_IOCTL_GETDEVICETYPEID:
2024 result = smartcard_GetDeviceTypeId_Call(ctx, out, operation);
2028 result = STATUS_UNSUCCESSFUL;
2038 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
2039 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
2041 offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
2042 const LONG rc = smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
2043 if (rc != SCARD_S_SUCCESS)
2047 if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
2048 (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
2049 (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
2051 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
2052 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
2055 *pIoStatus = STATUS_SUCCESS;
2057 if ((result & 0xC0000000L) == 0xC0000000L)
2060 *pIoStatus = result;
2062 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
2063 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
2066 Stream_SealLength(out);
2067 size_t outputBufferLength = Stream_Length(out);
2068 size_t dataEndPos = outputBufferLength;
2070 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
2071 outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
2072 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
2073 objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
2074 WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
2075 WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
2076 if (!Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH))
2077 return SCARD_E_BAD_SEEK;
2086 if (outputBufferLength > operation->outputBufferLength)
2088 WLog_Print(ctx->log, WLOG_DEBUG,
2089 "IRP warn: expected outputBufferLength %" PRIuz
", but current limit %" PRIu32
2090 ", respond with STATUS_BUFFER_TOO_SMALL for retransmit with larger buffer",
2091 outputBufferLength, operation->outputBufferLength);
2093 *pIoStatus = STATUS_BUFFER_TOO_SMALL;
2094 result = *pIoStatus;
2095 outputBufferLength = 0;
2096 objectBufferLength = 0;
2100 WLog_Print(ctx->log, WLOG_TRACE,
"IRP trace: outputBufferLength %" PRIuz
", limit %" PRIu32,
2101 outputBufferLength, operation->outputBufferLength);
2105 Stream_Write_UINT32(out, (UINT32)outputBufferLength);
2106 smartcard_pack_common_type_header(out);
2107 smartcard_pack_private_type_header(
2108 out, (UINT32)objectBufferLength);
2109 Stream_Write_INT32(out, result);
2110 if (result == STATUS_BUFFER_TOO_SMALL)
2111 Stream_SealLength(out);
2112 else if (!Stream_SetPosition(out, dataEndPos))
2113 return SCARD_E_BAD_SEEK;
2114 return SCARD_S_SUCCESS;
2117void context_free(
void* arg)
2119 struct s_scard_context_element* element = arg;
2123 if (element->fn_free)
2124 element->fn_free(element->context);
2128#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
2129scard_call_context* smartcard_call_context_new(
const rdpSettings* settings)
2132 if (!inst || !inst->context)
2134 return smartcard_call_context_new_with_context(inst->context);
2138scard_call_context* smartcard_call_context_new_with_context(rdpContext* context)
2140 WINPR_ASSERT(context);
2141 scard_call_context* ctx = calloc(1,
sizeof(scard_call_context));
2145 ctx->context = context;
2147 const rdpSettings* settings = context->settings;
2148 WINPR_ASSERT(settings);
2150 ctx->log = WLog_Get(SCARD_TAG);
2151 WINPR_ASSERT(ctx->log);
2153 ctx->stopEvent = CreateEventA(
nullptr, TRUE, FALSE,
nullptr);
2154 if (!ctx->stopEvent)
2157 ctx->names = LinkedList_New();
2161#if defined(WITH_SMARTCARD_EMULATE)
2165 if (ctx->useEmulatedCard)
2167#if defined(WITH_SMARTCARD_EMULATE)
2168 ctx->emulation = Emulate_New(settings);
2169 if (!ctx->emulation)
2172 WLog_Print(ctx->log, WLOG_ERROR,
"Smartcard emulation requested, but not supported!");
2181 ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
2183 if (!ctx->hWinSCardLibrary)
2185 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard library: '%s'",
2190 if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
2192 ctx->pWinSCardApi = &ctx->WinSCardApi;
2196 ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
2199 if (!ctx->pWinSCardApi)
2201 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard API!");
2206 ctx->rgSCardContextList = HashTable_New(FALSE);
2207 if (!ctx->rgSCardContextList)
2211 wObject* obj = HashTable_ValueObject(ctx->rgSCardContextList);
2218 WINPR_PRAGMA_DIAG_PUSH
2219 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2220 smartcard_call_context_free(ctx);
2221 WINPR_PRAGMA_DIAG_POP
2225void smartcard_call_context_free(scard_call_context* ctx)
2230 smartcard_call_context_signal_stop(ctx, FALSE);
2232 LinkedList_Free(ctx->names);
2233 if (ctx->StartedEvent)
2235 WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
2236 wrap_raw(ctx, SCardReleaseStartedEvent);
2239 if (ctx->useEmulatedCard)
2241#ifdef WITH_SMARTCARD_EMULATE
2244 Emulate_Free(ctx->emulation);
2245 ctx->emulation =
nullptr;
2250 if (ctx->hWinSCardLibrary)
2253 FreeLibrary(ctx->hWinSCardLibrary);
2254 ctx->hWinSCardLibrary =
nullptr;
2257 ctx->pWinSCardApi =
nullptr;
2259 HashTable_Free(ctx->rgSCardContextList);
2260 (void)CloseHandle(ctx->stopEvent);
2264BOOL smartcard_call_context_add(scard_call_context* ctx,
const char* name)
2268 return LinkedList_AddLast(ctx->names, name);
2271BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2274 if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
2276 wrap(ctx, SCardCancel, hContext);
2281BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2284 wrap(ctx, SCardReleaseContext, hContext);
2288BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
2293 HashTable_Clear(ctx->rgSCardContextList);
2297BOOL smarcard_call_set_callbacks(scard_call_context* ctx,
void* userdata,
2298 void* (*fn_new)(
void*, SCARDCONTEXT),
void (*fn_free)(
void*))
2301 ctx->userdata = userdata;
2302 ctx->fn_new = fn_new;
2303 ctx->fn_free = fn_free;
2307void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2309 struct s_scard_context_element* element =
nullptr;
2312 element = HashTable_GetItemValue(ctx->rgSCardContextList, (
void*)hContext);
2315 return element->context;
2318BOOL smartcard_call_is_configured(scard_call_context* ctx)
2322#if defined(WITH_SMARTCARD_EMULATE)
2323 if (ctx->useEmulatedCard)
2324 return Emulate_IsConfigured(ctx->emulation);
2330BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
2334 if (!ctx->stopEvent)
2338 return ResetEvent(ctx->stopEvent);
2340 return SetEvent(ctx->stopEvent);
WINPR_ATTR_NODISCARD FREERDP_API const void * freerdp_settings_get_pointer(const rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a immutable pointer settings value.
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree