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>
52#define wrap_raw(ctx, fkt, ...) \
53 ctx->useEmulatedCard ? Emulate_##fkt(ctx->emulation, ##__VA_ARGS__) \
54 : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
55#define wrap_ptr(ctx, fkt, ...) wrap_raw(ctx, fkt, ##__VA_ARGS__)
57#define wrap_raw(ctx, fkt, ...) \
58 ctx->useEmulatedCard ? SCARD_F_INTERNAL_ERROR : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
59#define wrap_ptr(ctx, fkt, ...) \
60 ctx->useEmulatedCard ? nullptr : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
64#define wrap(ctx, fkt, ...) wrap_raw(ctx, fkt, ##__VA_ARGS__)
66#define wrap(ctx, fkt, ...) \
68 LONG defstatus = wrap_raw(ctx, fkt, ##__VA_ARGS__); \
69 if (defstatus != SCARD_S_SUCCESS) \
70 WLog_Print(ctx->log, WLOG_TRACE, "[" #fkt "] failed with %s", \
71 SCardGetErrorString(defstatus)); \
76struct s_scard_call_context
81 wHashTable* rgSCardContextList;
82#if defined(WITH_SMARTCARD_EMULATE)
83 SmartcardEmulationContext* emulation;
85 HANDLE hWinSCardLibrary;
91 void* (*fn_new)(
void*, SCARDCONTEXT);
92 void (*fn_free)(
void*);
97struct s_scard_context_element
100 void (*fn_free)(
void*);
103static void context_free(
void* arg);
105WINPR_ATTR_NODISCARD WINPR_ATTR_NODISCARD
static LONG
106smartcard_EstablishContext_Call(scard_call_context* smartcard,
wStream* out,
109 SCARDCONTEXT hContext = WINPR_C_ARRAY_INIT;
112 LONG status = ret.ReturnCode =
113 wrap(smartcard, SCardEstablishContext, call->dwScope,
nullptr,
nullptr, &hContext);
115 if (ret.ReturnCode == SCARD_S_SUCCESS)
117 const void* key = (
void*)(
size_t)hContext;
118 struct s_scard_context_element* pContext =
119 calloc(1,
sizeof(
struct s_scard_context_element));
121 return STATUS_NO_MEMORY;
123 pContext->fn_free = smartcard->fn_free;
125 if (smartcard->fn_new)
127 pContext->context = smartcard->fn_new(smartcard->userdata, hContext);
128 if (!pContext->context)
131 return STATUS_NO_MEMORY;
135 if (!HashTable_Insert(smartcard->rgSCardContextList, key, (
void*)pContext))
137 WLog_Print(smartcard->log, WLOG_ERROR,
"HashTable_Insert failed!");
138 context_free(pContext);
139 return STATUS_INTERNAL_ERROR;
144 return scard_log_status_error_wlog(smartcard->log,
"SCardEstablishContext", status);
148 smartcard_scard_context_native_to_redir(&(ret.hContext), hContext);
150 status = smartcard_pack_establish_context_return(out, &ret);
151 if (status != SCARD_S_SUCCESS)
153 return scard_log_status_error_wlog(smartcard->log,
154 "smartcard_pack_establish_context_return", status);
157 return ret.ReturnCode;
160WINPR_ATTR_NODISCARD
static LONG smartcard_ReleaseContext_Call(scard_call_context* smartcard,
161 WINPR_ATTR_UNUSED
wStream* out,
166 WINPR_ASSERT(smartcard);
168 WINPR_ASSERT(operation);
170 ret.ReturnCode = wrap(smartcard, SCardReleaseContext, operation->hContext);
172 if (ret.ReturnCode == SCARD_S_SUCCESS)
173 HashTable_Remove(smartcard->rgSCardContextList, (
void*)operation->hContext);
176 return scard_log_status_error_wlog(smartcard->log,
"SCardReleaseContext", ret.ReturnCode);
179 smartcard_trace_long_return_int(smartcard->log, &ret,
"ReleaseContext");
180 return ret.ReturnCode;
183WINPR_ATTR_NODISCARD
static LONG smartcard_IsValidContext_Call(scard_call_context* smartcard,
184 WINPR_ATTR_UNUSED
wStream* out,
189 WINPR_ASSERT(smartcard);
191 WINPR_ASSERT(operation);
193 ret.ReturnCode = wrap(smartcard, SCardIsValidContext, operation->hContext);
194 smartcard_trace_long_return_int(smartcard->log, &ret,
"IsValidContext");
195 return ret.ReturnCode;
198WINPR_ATTR_NODISCARD
static LONG smartcard_ListReaderGroupsA_Call(scard_call_context* smartcard,
204 LPSTR mszGroups =
nullptr;
207 WINPR_ASSERT(smartcard);
209 WINPR_ASSERT(operation);
211 cchGroups = SCARD_AUTOALLOCATE;
213 wrap(smartcard, SCardListReaderGroupsA, operation->hContext, (LPSTR)&mszGroups, &cchGroups);
214 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchGroups == SCARD_AUTOALLOCATE))
215 return SCARD_F_UNKNOWN_ERROR;
217 ret.msz = (BYTE*)mszGroups;
218 ret.cBytes = cchGroups;
220 status = smartcard_pack_list_reader_groups_return(out, &ret, FALSE);
222 if (status != SCARD_S_SUCCESS)
226 wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
228 return ret.ReturnCode;
231WINPR_ATTR_NODISCARD
static LONG smartcard_ListReaderGroupsW_Call(scard_call_context* smartcard,
237 LPWSTR mszGroups =
nullptr;
240 WINPR_ASSERT(smartcard);
242 WINPR_ASSERT(operation);
244 cchGroups = SCARD_AUTOALLOCATE;
245 status = ret.ReturnCode = wrap(smartcard, SCardListReaderGroupsW, operation->hContext,
246 (LPWSTR)&mszGroups, &cchGroups);
247 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchGroups == SCARD_AUTOALLOCATE))
248 return SCARD_F_UNKNOWN_ERROR;
250 ret.msz = (BYTE*)mszGroups;
252 WINPR_ASSERT(cchGroups < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
253 const size_t blen =
sizeof(WCHAR) * cchGroups;
254 WINPR_ASSERT(blen <= UINT32_MAX);
255 ret.cBytes = (UINT32)blen;
257 if (status != SCARD_S_SUCCESS)
260 status = smartcard_pack_list_reader_groups_return(out, &ret, TRUE);
262 if (status != SCARD_S_SUCCESS)
266 wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
268 return ret.ReturnCode;
272static BOOL filter_match(wLinkedList* list, LPCSTR reader,
size_t readerLen)
277 LinkedList_Enumerator_Reset(list);
279 while (LinkedList_Enumerator_MoveNext(list))
281 const char* filter = LinkedList_Enumerator_Current(list);
285 if (strstr(reader, filter) !=
nullptr)
294static DWORD filter_device_by_name_a(wLinkedList* list, LPSTR* mszReaders, DWORD cchReaders)
299 if (*mszReaders ==
nullptr || LinkedList_Count(list) < 1)
304 LPCSTR rreader = &(*mszReaders)[rpos];
305 LPSTR wreader = &(*mszReaders)[wpos];
306 size_t readerLen = strnlen(rreader, cchReaders - rpos);
308 rpos += readerLen + 1;
310 if (filter_match(list, rreader, readerLen))
312 if (rreader != wreader)
313 memmove(wreader, rreader, readerLen + 1);
315 wpos += readerLen + 1;
317 }
while (rpos < cchReaders);
322 if (wpos >= cchReaders)
325 (*mszReaders)[wpos++] =
'\0';
332static DWORD filter_device_by_name_w(wLinkedList* list, LPWSTR* mszReaders, DWORD cchReaders)
335 LPSTR readers =
nullptr;
337 if (LinkedList_Count(list) < 1)
340 readers = ConvertMszWCharNToUtf8Alloc(*mszReaders, cchReaders,
nullptr);
348 *mszReaders =
nullptr;
349 rc = filter_device_by_name_a(list, &readers, cchReaders);
351 *mszReaders = ConvertMszUtf8NToWCharAlloc(readers, rc,
nullptr);
359WINPR_ATTR_NODISCARD
static LONG smartcard_ListReadersA_Call(scard_call_context* smartcard,
364 LPSTR mszReaders =
nullptr;
366 WINPR_ASSERT(smartcard);
368 WINPR_ASSERT(operation);
371 DWORD cchReaders = SCARD_AUTOALLOCATE;
372 LONG status = ret.ReturnCode = wrap(smartcard, SCardListReadersA, operation->hContext,
373 (LPCSTR)call->mszGroups, (LPSTR)&mszReaders, &cchReaders);
374 if (status == SCARD_S_SUCCESS)
376 if (cchReaders == SCARD_AUTOALLOCATE)
377 status = SCARD_F_UNKNOWN_ERROR;
380 if (status != SCARD_S_SUCCESS)
382 (void)scard_log_status_error_wlog(smartcard->log,
"SCardListReadersA", status);
383 return smartcard_pack_list_readers_return(out, &ret, FALSE);
386 void* original = mszReaders;
387 cchReaders = filter_device_by_name_a(smartcard->names, &mszReaders, cchReaders);
388 ret.msz = (BYTE*)mszReaders;
389 ret.cBytes = cchReaders;
391 status = smartcard_pack_list_readers_return(out, &ret, FALSE);
393 wrap(smartcard, SCardFreeMemory, operation->hContext, original);
395 if (status != SCARD_S_SUCCESS)
396 return scard_log_status_error_wlog(smartcard->log,
"smartcard_pack_list_readers_return",
399 return ret.ReturnCode;
402WINPR_ATTR_NODISCARD
static LONG smartcard_ListReadersW_Call(scard_call_context* smartcard,
408 DWORD cchReaders = 0;
424 WINPR_ASSERT(smartcard);
425 WINPR_ASSERT(operation);
427 call = &operation->call.listReaders;
429 string.bp = call->mszGroups;
430 cchReaders = SCARD_AUTOALLOCATE;
431 status = ret.ReturnCode = wrap(smartcard, SCardListReadersW, operation->hContext,
string.wz,
432 (LPWSTR)&mszReaders.pw, &cchReaders);
433 if (status == SCARD_S_SUCCESS)
435 if (cchReaders == SCARD_AUTOALLOCATE)
436 status = SCARD_F_UNKNOWN_ERROR;
439 if (status != SCARD_S_SUCCESS)
441 (void)scard_log_status_error_wlog(smartcard->log,
"SCardListReadersW", status);
442 return smartcard_pack_list_readers_return(out, &ret, TRUE);
445 void* original = mszReaders.pb;
446 cchReaders = filter_device_by_name_w(smartcard->names, &mszReaders.pw, cchReaders);
447 ret.msz = mszReaders.pb;
448 ret.cBytes = cchReaders *
sizeof(WCHAR);
449 status = smartcard_pack_list_readers_return(out, &ret, TRUE);
452 wrap(smartcard, SCardFreeMemory, operation->hContext, original);
454 if (status != SCARD_S_SUCCESS)
457 return ret.ReturnCode;
460WINPR_ATTR_NODISCARD
static LONG
461smartcard_IntroduceReaderGroupA_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
467 WINPR_ASSERT(smartcard);
469 WINPR_ASSERT(operation);
471 call = &operation->call.contextAndStringA;
472 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupA, operation->hContext, call->sz);
473 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderGroupA", ret.ReturnCode);
474 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderGroupA");
475 return ret.ReturnCode;
478WINPR_ATTR_NODISCARD
static LONG
479smartcard_IntroduceReaderGroupW_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
485 WINPR_ASSERT(smartcard);
487 WINPR_ASSERT(operation);
489 call = &operation->call.contextAndStringW;
490 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupW, operation->hContext, call->sz);
491 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderGroupW", ret.ReturnCode);
492 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderGroupW");
493 return ret.ReturnCode;
496WINPR_ATTR_NODISCARD
static LONG smartcard_IntroduceReaderA_Call(scard_call_context* smartcard,
497 WINPR_ATTR_UNUSED
wStream* out,
503 WINPR_ASSERT(smartcard);
505 WINPR_ASSERT(operation);
507 call = &operation->call.contextAndTwoStringA;
509 wrap(smartcard, SCardIntroduceReaderA, operation->hContext, call->sz1, call->sz2);
510 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderA", ret.ReturnCode);
511 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderA");
512 return ret.ReturnCode;
515WINPR_ATTR_NODISCARD
static LONG smartcard_IntroduceReaderW_Call(scard_call_context* smartcard,
516 WINPR_ATTR_UNUSED
wStream* out,
522 WINPR_ASSERT(smartcard);
524 WINPR_ASSERT(operation);
526 call = &operation->call.contextAndTwoStringW;
528 wrap(smartcard, SCardIntroduceReaderW, operation->hContext, call->sz1, call->sz2);
529 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderW", ret.ReturnCode);
530 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderW");
531 return ret.ReturnCode;
534WINPR_ATTR_NODISCARD
static LONG smartcard_ForgetReaderA_Call(scard_call_context* smartcard,
535 WINPR_ATTR_UNUSED
wStream* out,
541 WINPR_ASSERT(smartcard);
543 WINPR_ASSERT(operation);
545 call = &operation->call.contextAndStringA;
546 ret.ReturnCode = wrap(smartcard, SCardForgetReaderA, operation->hContext, call->sz);
547 scard_log_status_error_wlog(smartcard->log,
"SCardForgetReaderA", ret.ReturnCode);
548 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardForgetReaderA");
549 return ret.ReturnCode;
552WINPR_ATTR_NODISCARD
static LONG smartcard_ForgetReaderW_Call(scard_call_context* smartcard,
553 WINPR_ATTR_UNUSED
wStream* out,
559 WINPR_ASSERT(smartcard);
561 WINPR_ASSERT(operation);
563 call = &operation->call.contextAndStringW;
564 ret.ReturnCode = wrap(smartcard, SCardForgetReaderW, operation->hContext, call->sz);
565 scard_log_status_error_wlog(smartcard->log,
"SCardForgetReaderW", ret.ReturnCode);
566 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardForgetReaderW");
567 return ret.ReturnCode;
570WINPR_ATTR_NODISCARD
static LONG smartcard_AddReaderToGroupA_Call(scard_call_context* smartcard,
571 WINPR_ATTR_UNUSED
wStream* out,
577 WINPR_ASSERT(smartcard);
579 WINPR_ASSERT(operation);
581 call = &operation->call.contextAndTwoStringA;
583 wrap(smartcard, SCardAddReaderToGroupA, operation->hContext, call->sz1, call->sz2);
584 scard_log_status_error_wlog(smartcard->log,
"SCardAddReaderToGroupA", ret.ReturnCode);
585 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardAddReaderToGroupA");
586 return ret.ReturnCode;
589WINPR_ATTR_NODISCARD
static LONG smartcard_AddReaderToGroupW_Call(scard_call_context* smartcard,
590 WINPR_ATTR_UNUSED
wStream* out,
596 WINPR_ASSERT(smartcard);
598 WINPR_ASSERT(operation);
600 call = &operation->call.contextAndTwoStringW;
602 wrap(smartcard, SCardAddReaderToGroupW, operation->hContext, call->sz1, call->sz2);
603 scard_log_status_error_wlog(smartcard->log,
"SCardAddReaderToGroupW", ret.ReturnCode);
604 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardAddReaderToGroupA");
605 return ret.ReturnCode;
608WINPR_ATTR_NODISCARD
static LONG
609smartcard_RemoveReaderFromGroupA_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
615 WINPR_ASSERT(smartcard);
617 WINPR_ASSERT(operation);
619 call = &operation->call.contextAndTwoStringA;
621 wrap(smartcard, SCardRemoveReaderFromGroupA, operation->hContext, call->sz1, call->sz2);
622 scard_log_status_error_wlog(smartcard->log,
"SCardRemoveReaderFromGroupA", ret.ReturnCode);
623 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardRemoveReaderFromGroupA");
624 return ret.ReturnCode;
627WINPR_ATTR_NODISCARD
static LONG
628smartcard_RemoveReaderFromGroupW_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
634 WINPR_ASSERT(smartcard);
636 WINPR_ASSERT(operation);
638 call = &operation->call.contextAndTwoStringW;
640 wrap(smartcard, SCardRemoveReaderFromGroupW, operation->hContext, call->sz1, call->sz2);
641 scard_log_status_error_wlog(smartcard->log,
"SCardRemoveReaderFromGroupW", ret.ReturnCode);
642 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardRemoveReaderFromGroupW");
643 return ret.ReturnCode;
646WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsA_Call(scard_call_context* smartcard,
654 WINPR_ASSERT(smartcard);
655 WINPR_ASSERT(operation);
657 call = &operation->call.locateCardsA;
659 ret.ReturnCode = wrap(smartcard, SCardLocateCardsA, operation->hContext, call->mszCards,
660 call->rgReaderStates, call->cReaders);
661 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsA", ret.ReturnCode);
662 ret.rgReaderStates =
nullptr;
664 if (call->cReaders > 0)
669 if (!ret.rgReaderStates)
670 return STATUS_NO_MEMORY;
671 ret.cReaders = call->cReaders;
674 for (UINT32 x = 0; x < ret.cReaders; x++)
679 cur->dwCurrentState = cstate->dwCurrentState;
680 cur->dwEventState = cstate->dwEventState;
681 cur->cbAtr = cstate->cbAtr;
682 CopyMemory(&(cur->rgbAtr), &(cstate->rgbAtr),
sizeof(cur->rgbAtr));
683 if (!smartcard_reader_state_return_is_valid(x, cur))
685 free(ret.rgReaderStates);
686 return SCARD_E_INVALID_ATR;
690 status = smartcard_pack_locate_cards_return(out, &ret);
691 free(ret.rgReaderStates);
693 if (status != SCARD_S_SUCCESS)
696 return ret.ReturnCode;
699WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsW_Call(scard_call_context* smartcard,
706 WINPR_ASSERT(smartcard);
707 WINPR_ASSERT(operation);
711 ret.ReturnCode = wrap(smartcard, SCardLocateCardsW, operation->hContext, call->mszCards,
712 call->rgReaderStates, call->cReaders);
713 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsW", ret.ReturnCode);
714 ret.rgReaderStates =
nullptr;
716 if (call->cReaders > 0)
721 if (!ret.rgReaderStates)
722 return STATUS_NO_MEMORY;
723 ret.cReaders = call->cReaders;
726 for (UINT32 x = 0; x < ret.cReaders; x++)
731 cur->dwCurrentState = cstate->dwCurrentState;
732 cur->dwEventState = cstate->dwEventState;
733 cur->cbAtr = cstate->cbAtr;
734 CopyMemory(&(cur->rgbAtr), &(cstate->rgbAtr),
sizeof(cur->rgbAtr));
735 if (!smartcard_reader_state_return_is_valid(x, cur))
737 free(ret.rgReaderStates);
738 return SCARD_E_INVALID_ATR;
742 status = smartcard_pack_locate_cards_return(out, &ret);
743 free(ret.rgReaderStates);
745 if (status != SCARD_S_SUCCESS)
748 return ret.ReturnCode;
751WINPR_ATTR_NODISCARD
static LONG smartcard_ReadCacheA_Call(scard_call_context* smartcard,
760 WINPR_ASSERT(smartcard);
762 WINPR_ASSERT(operation);
764 call = &operation->call.readCacheA;
765 autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE);
767 if (!call->Common.fPbDataIsNULL)
771 ret.pbData = malloc(call->Common.cbDataLen);
773 return SCARD_F_INTERNAL_ERROR;
775 ret.cbDataLen = call->Common.cbDataLen;
779 ret.ReturnCode = wrap(smartcard, SCardReadCacheA, operation->hContext,
780 call->Common.CardIdentifier, call->Common.FreshnessCounter,
781 call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
784 wrap(smartcard, SCardReadCacheA, operation->hContext, call->Common.CardIdentifier,
785 call->Common.FreshnessCounter, call->szLookupName, ret.pbData, &ret.cbDataLen);
787 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, call->szLookupName,
790 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
791 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
793 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheA", ret.ReturnCode);
796 status = smartcard_pack_read_cache_return(out, &ret);
798 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
801 if (status != SCARD_S_SUCCESS)
804 return ret.ReturnCode;
807WINPR_ATTR_NODISCARD
static LONG smartcard_ReadCacheW_Call(scard_call_context* smartcard,
815 WINPR_ASSERT(smartcard);
817 WINPR_ASSERT(operation);
819 call = &operation->call.readCacheW;
821 if (!call->Common.fPbDataIsNULL)
822 ret.cbDataLen = SCARD_AUTOALLOCATE;
825 wrap(smartcard, SCardReadCacheW, operation->hContext, call->Common.CardIdentifier,
826 call->Common.FreshnessCounter, call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
828 if (WLog_IsLevelActive(smartcard->log, WLOG_TRACE))
830 char buffer[128] = WINPR_C_ARRAY_INIT;
831 (void)ConvertWCharToUtf8(call->szLookupName, buffer,
sizeof(buffer));
832 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, buffer, ret.cbDataLen);
834 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
835 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
837 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheW", ret.ReturnCode);
840 status = smartcard_pack_read_cache_return(out, &ret);
842 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
844 if (status != SCARD_S_SUCCESS)
847 return ret.ReturnCode;
850WINPR_ATTR_NODISCARD
static LONG smartcard_WriteCacheA_Call(scard_call_context* smartcard,
851 WINPR_ATTR_UNUSED
wStream* out,
857 WINPR_ASSERT(smartcard);
859 WINPR_ASSERT(operation);
861 call = &operation->call.writeCacheA;
863 ret.ReturnCode = wrap(smartcard, SCardWriteCacheA, operation->hContext,
864 call->Common.CardIdentifier, call->Common.FreshnessCounter,
865 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
866 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheA", ret.ReturnCode);
867 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheA");
868 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, call->szLookupName,
869 call->Common.cbDataLen);
870 return ret.ReturnCode;
873WINPR_ATTR_NODISCARD
static LONG smartcard_WriteCacheW_Call(scard_call_context* smartcard,
874 WINPR_ATTR_UNUSED
wStream* out,
880 WINPR_ASSERT(smartcard);
882 WINPR_ASSERT(operation);
884 call = &operation->call.writeCacheW;
886 ret.ReturnCode = wrap(smartcard, SCardWriteCacheW, operation->hContext,
887 call->Common.CardIdentifier, call->Common.FreshnessCounter,
888 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
889 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheW", ret.ReturnCode);
890 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheW");
892 if (WLog_IsLevelActive(smartcard->log, WLOG_TRACE))
894 char buffer[128] = WINPR_C_ARRAY_INIT;
895 (void)ConvertWCharToUtf8(call->szLookupName, buffer,
sizeof(buffer));
896 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, buffer,
897 call->Common.cbDataLen);
899 return ret.ReturnCode;
902WINPR_ATTR_NODISCARD
static LONG smartcard_GetTransmitCount_Call(scard_call_context* smartcard,
909 WINPR_ASSERT(smartcard);
911 WINPR_ASSERT(operation);
913 ret.ReturnCode = wrap(smartcard, SCardGetTransmitCount, operation->hCard, &ret.cTransmitCount);
914 scard_log_status_error_wlog(smartcard->log,
"SCardGetTransmitCount", ret.ReturnCode);
915 status = smartcard_pack_get_transmit_count_return(out, &ret);
916 if (status != SCARD_S_SUCCESS)
919 return ret.ReturnCode;
922WINPR_ATTR_NODISCARD
static LONG smartcard_ReleaseStartedEvent_Call(scard_call_context* smartcard,
926 WINPR_UNUSED(smartcard);
928 WINPR_UNUSED(operation);
930 WLog_Print(smartcard->log, WLOG_WARN,
931 "According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
932 "this is not supported?!?");
933 return SCARD_E_UNSUPPORTED_FEATURE;
936WINPR_ATTR_NODISCARD
static LONG smartcard_GetReaderIcon_Call(scard_call_context* smartcard,
944 WINPR_ASSERT(smartcard);
946 WINPR_ASSERT(operation);
948 call = &operation->call.getReaderIcon;
950 ret.cbDataLen = SCARD_AUTOALLOCATE;
951 ret.ReturnCode = wrap(smartcard, SCardGetReaderIconW, operation->hContext, call->szReaderName,
952 (LPBYTE)&ret.pbData, &ret.cbDataLen);
953 scard_log_status_error_wlog(smartcard->log,
"SCardGetReaderIconW", ret.ReturnCode);
954 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cbDataLen == SCARD_AUTOALLOCATE))
955 return SCARD_F_UNKNOWN_ERROR;
957 status = smartcard_pack_get_reader_icon_return(out, &ret);
958 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
959 if (status != SCARD_S_SUCCESS)
962 return ret.ReturnCode;
965WINPR_ATTR_NODISCARD
static LONG smartcard_GetDeviceTypeId_Call(scard_call_context* smartcard,
973 WINPR_ASSERT(smartcard);
975 WINPR_ASSERT(operation);
977 call = &operation->call.getDeviceTypeId;
979 ret.ReturnCode = wrap(smartcard, SCardGetDeviceTypeIdW, operation->hContext, call->szReaderName,
981 scard_log_status_error_wlog(smartcard->log,
"SCardGetDeviceTypeIdW", ret.ReturnCode);
983 status = smartcard_pack_device_type_id_return(out, &ret);
984 if (status != SCARD_S_SUCCESS)
987 return ret.ReturnCode;
991static BOOL smartcard_context_was_aborted(scard_call_context* smartcard)
993 WINPR_ASSERT(smartcard);
995 HANDLE handles[] = { smartcard->stopEvent, freerdp_abort_event(smartcard->context) };
996 const DWORD rc = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, 0);
997 return (rc >= WAIT_OBJECT_0) && (rc <= WAIT_OBJECT_0 + ARRAYSIZE(handles));
1000WINPR_ATTR_NODISCARD
static LONG smartcard_GetStatusChangeA_Call(scard_call_context* smartcard,
1004 LONG status = STATUS_NO_MEMORY;
1005 DWORD dwTimeOut = 0;
1006 const DWORD dwTimeStep = 100;
1011 WINPR_ASSERT(smartcard);
1013 WINPR_ASSERT(operation);
1015 call = &operation->call.getStatusChangeA;
1016 dwTimeOut = call->dwTimeOut;
1018 if (call->cReaders > 0)
1021 ret.rgReaderStates =
1023 if (!rgReaderStates || !ret.rgReaderStates)
1026 ret.cReaders = call->cReaders;
1029 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
1031 if (call->cReaders > 0)
1032 memcpy(rgReaderStates, call->rgReaderStates,
1034 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1035 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
1036 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1038 if (smartcard_context_was_aborted(smartcard))
1040 if (dwTimeOut != INFINITE)
1043 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", ret.ReturnCode);
1045 status = SCARD_E_INVALID_ATR;
1046 for (UINT32 index = 0; index < ret.cReaders; index++)
1051 rout->dwCurrentState = cur->dwCurrentState;
1052 rout->dwEventState = cur->dwEventState;
1053 rout->cbAtr = cur->cbAtr;
1054 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1055 if (!smartcard_reader_state_return_is_valid(index, rout))
1059 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1061 free(ret.rgReaderStates);
1062 free(rgReaderStates);
1063 if (status != SCARD_S_SUCCESS)
1065 return ret.ReturnCode;
1068WINPR_ATTR_NODISCARD
static LONG smartcard_GetStatusChangeW_Call(scard_call_context* smartcard,
1072 LONG status = STATUS_NO_MEMORY;
1073 DWORD dwTimeOut = 0;
1074 const DWORD dwTimeStep = 100;
1078 WINPR_ASSERT(smartcard);
1080 WINPR_ASSERT(operation);
1083 dwTimeOut = call->dwTimeOut;
1085 if (call->cReaders > 0)
1088 ret.rgReaderStates =
1090 if (!rgReaderStates || !ret.rgReaderStates)
1093 ret.cReaders = call->cReaders;
1096 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
1098 if (call->cReaders > 0)
1099 memcpy(rgReaderStates, call->rgReaderStates,
1102 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
1103 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
1105 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1107 if (smartcard_context_was_aborted(smartcard))
1109 if (dwTimeOut != INFINITE)
1112 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeW", ret.ReturnCode);
1114 status = SCARD_E_INVALID_ATR;
1115 for (UINT32 index = 0; index < ret.cReaders; index++)
1120 rout->dwCurrentState = cur->dwCurrentState;
1121 rout->dwEventState = cur->dwEventState;
1122 rout->cbAtr = cur->cbAtr;
1123 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1124 if (!smartcard_reader_state_return_is_valid(index, rout))
1128 status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
1130 free(ret.rgReaderStates);
1131 free(rgReaderStates);
1132 if (status != SCARD_S_SUCCESS)
1134 return ret.ReturnCode;
1137WINPR_ATTR_NODISCARD
static LONG smartcard_Cancel_Call(scard_call_context* smartcard,
1138 WINPR_ATTR_UNUSED
wStream* out,
1143 WINPR_ASSERT(smartcard);
1145 WINPR_ASSERT(operation);
1147 ret.ReturnCode = wrap(smartcard, SCardCancel, operation->hContext);
1148 scard_log_status_error_wlog(smartcard->log,
"SCardCancel", ret.ReturnCode);
1149 smartcard_trace_long_return_int(smartcard->log, &ret,
"Cancel");
1150 return ret.ReturnCode;
1153WINPR_ATTR_NODISCARD
static LONG
1157 SCARDHANDLE hCard = 0;
1161 WINPR_ASSERT(smartcard);
1163 WINPR_ASSERT(operation);
1165 call = &operation->call.connectA;
1167 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1168 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1170 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1173 ret.ReturnCode = wrap(smartcard, SCardConnectA, operation->hContext, (
char*)call->szReader,
1174 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1175 &ret.dwActiveProtocol);
1176 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1177 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1179 status = smartcard_pack_connect_return(out, &ret);
1180 if (status != SCARD_S_SUCCESS)
1183 status = ret.ReturnCode;
1189WINPR_ATTR_NODISCARD
static LONG
1193 SCARDHANDLE hCard = 0;
1197 WINPR_ASSERT(smartcard);
1199 WINPR_ASSERT(operation);
1201 call = &operation->call.connectW;
1203 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1204 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1206 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1209 ret.ReturnCode = wrap(smartcard, SCardConnectW, operation->hContext, (WCHAR*)call->szReader,
1210 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1211 &ret.dwActiveProtocol);
1212 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1213 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1215 status = smartcard_pack_connect_return(out, &ret);
1216 if (status != SCARD_S_SUCCESS)
1219 status = ret.ReturnCode;
1225WINPR_ATTR_NODISCARD
static LONG smartcard_Reconnect_Call(scard_call_context* smartcard,
1233 WINPR_ASSERT(smartcard);
1235 WINPR_ASSERT(operation);
1237 call = &operation->call.reconnect;
1239 wrap(smartcard, SCardReconnect, operation->hCard, call->dwShareMode,
1240 call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
1241 scard_log_status_error_wlog(smartcard->log,
"SCardReconnect", ret.ReturnCode);
1242 status = smartcard_pack_reconnect_return(out, &ret);
1243 if (status != SCARD_S_SUCCESS)
1246 return ret.ReturnCode;
1249WINPR_ATTR_NODISCARD
static LONG smartcard_Disconnect_Call(scard_call_context* smartcard,
1250 WINPR_ATTR_UNUSED
wStream* out,
1256 WINPR_ASSERT(smartcard);
1258 WINPR_ASSERT(operation);
1260 call = &operation->call.hCardAndDisposition;
1262 ret.ReturnCode = wrap(smartcard, SCardDisconnect, operation->hCard, call->dwDisposition);
1263 scard_log_status_error_wlog(smartcard->log,
"SCardDisconnect", ret.ReturnCode);
1264 smartcard_trace_long_return_int(smartcard->log, &ret,
"Disconnect");
1266 return ret.ReturnCode;
1269WINPR_ATTR_NODISCARD
static LONG smartcard_BeginTransaction_Call(scard_call_context* smartcard,
1270 WINPR_ATTR_UNUSED
wStream* out,
1275 WINPR_ASSERT(smartcard);
1277 WINPR_ASSERT(operation);
1279 ret.ReturnCode = wrap(smartcard, SCardBeginTransaction, operation->hCard);
1280 scard_log_status_error_wlog(smartcard->log,
"SCardBeginTransaction", ret.ReturnCode);
1281 smartcard_trace_long_return_int(smartcard->log, &ret,
"BeginTransaction");
1282 return ret.ReturnCode;
1285WINPR_ATTR_NODISCARD
static LONG smartcard_EndTransaction_Call(scard_call_context* smartcard,
1286 WINPR_ATTR_UNUSED
wStream* out,
1292 WINPR_ASSERT(smartcard);
1294 WINPR_ASSERT(operation);
1296 call = &operation->call.hCardAndDisposition;
1298 ret.ReturnCode = wrap(smartcard, SCardEndTransaction, operation->hCard, call->dwDisposition);
1299 scard_log_status_error_wlog(smartcard->log,
"SCardEndTransaction", ret.ReturnCode);
1300 smartcard_trace_long_return_int(smartcard->log, &ret,
"EndTransaction");
1301 return ret.ReturnCode;
1304WINPR_ATTR_NODISCARD
static LONG smartcard_State_Call(scard_call_context* smartcard,
wStream* out,
1310 WINPR_ASSERT(smartcard);
1312 WINPR_ASSERT(operation);
1314 ret.cbAtrLen = SCARD_ATR_LENGTH;
1315 ret.ReturnCode = wrap(smartcard, SCardState, operation->hCard, &ret.dwState, &ret.dwProtocol,
1316 (BYTE*)&ret.rgAtr, &ret.cbAtrLen);
1318 scard_log_status_error_wlog(smartcard->log,
"SCardState", ret.ReturnCode);
1319 status = smartcard_pack_state_return(out, &ret);
1320 if (status != SCARD_S_SUCCESS)
1323 return ret.ReturnCode;
1326WINPR_ATTR_NODISCARD
static LONG smartcard_StatusA_Call(scard_call_context* smartcard,
wStream* out,
1331 DWORD cchReaderLen = 0;
1333 LPSTR mszReaderNames =
nullptr;
1336 WINPR_ASSERT(smartcard);
1338 WINPR_ASSERT(operation);
1340 call = &operation->call.status;
1342 call->cbAtrLen = 32;
1343 cbAtrLen = call->cbAtrLen;
1345 if (call->fmszReaderNamesIsNULL)
1348 cchReaderLen = SCARD_AUTOALLOCATE;
1350 status = ret.ReturnCode =
1351 wrap(smartcard, SCardStatusA, operation->hCard,
1352 call->fmszReaderNamesIsNULL ?
nullptr : (LPSTR)&mszReaderNames, &cchReaderLen,
1353 &ret.dwState, &ret.dwProtocol, cbAtrLen ? (BYTE*)&ret.pbAtr : nullptr, &cbAtrLen);
1355 scard_log_status_error_wlog(smartcard->log,
"SCardStatusA", status);
1356 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchReaderLen == SCARD_AUTOALLOCATE))
1357 return SCARD_F_UNKNOWN_ERROR;
1359 if (status == SCARD_S_SUCCESS)
1361 if (!call->fmszReaderNamesIsNULL)
1362 ret.mszReaderNames = (BYTE*)mszReaderNames;
1364 ret.cBytes = cchReaderLen;
1367 ret.cbAtrLen = cbAtrLen;
1370 status = smartcard_pack_status_return(out, &ret, FALSE);
1373 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1375 if (status != SCARD_S_SUCCESS)
1377 return ret.ReturnCode;
1380WINPR_ATTR_NODISCARD
static LONG smartcard_StatusW_Call(scard_call_context* smartcard,
wStream* out,
1385 LPWSTR mszReaderNames =
nullptr;
1389 WINPR_ASSERT(smartcard);
1391 WINPR_ASSERT(operation);
1393 call = &operation->call.status;
1399 cbAtrLen = call->cbAtrLen = 32;
1401 if (call->fmszReaderNamesIsNULL)
1404 ret.cBytes = SCARD_AUTOALLOCATE;
1406 status = ret.ReturnCode =
1407 wrap(smartcard, SCardStatusW, operation->hCard,
1408 call->fmszReaderNamesIsNULL ?
nullptr : (LPWSTR)&mszReaderNames, &ret.cBytes,
1409 &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
1410 scard_log_status_error_wlog(smartcard->log,
"SCardStatusW", status);
1411 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cBytes == SCARD_AUTOALLOCATE))
1412 return SCARD_F_UNKNOWN_ERROR;
1415 if (status == SCARD_S_SUCCESS)
1417 if (!call->fmszReaderNamesIsNULL)
1418 ret.mszReaderNames = (BYTE*)mszReaderNames;
1420 ret.cbAtrLen = cbAtrLen;
1423 if (ret.cBytes != SCARD_AUTOALLOCATE)
1426 WINPR_ASSERT(ret.cBytes < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
1427 blen =
sizeof(WCHAR) * ret.cBytes;
1428 WINPR_ASSERT(blen <= UINT32_MAX);
1429 ret.cBytes = (UINT32)blen;
1432 status = smartcard_pack_status_return(out, &ret, TRUE);
1433 if (status != SCARD_S_SUCCESS)
1437 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1439 return ret.ReturnCode;
1442WINPR_ATTR_NODISCARD
static LONG
1449 WINPR_ASSERT(smartcard);
1451 WINPR_ASSERT(operation);
1453 call = &operation->call.transmit;
1454 ret.cbRecvLength = 0;
1455 ret.pbRecvBuffer =
nullptr;
1457 if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
1459 if (call->cbRecvLength >= 66560)
1460 call->cbRecvLength = 66560;
1462 const UINT32 cbRecvLength = call->cbRecvLength;
1463 ret.pbRecvBuffer = (BYTE*)malloc(cbRecvLength);
1465 if (!ret.pbRecvBuffer)
1466 return STATUS_NO_MEMORY;
1467 ret.cbRecvLength = cbRecvLength;
1470 ret.pioRecvPci = call->pioRecvPci;
1472 wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
1473 call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
1475 scard_log_status_error_wlog(smartcard->log,
"SCardTransmit", ret.ReturnCode);
1477 status = smartcard_pack_transmit_return(out, &ret);
1478 free(ret.pbRecvBuffer);
1480 if (status != SCARD_S_SUCCESS)
1482 return ret.ReturnCode;
1485WINPR_ATTR_NODISCARD
static LONG smartcard_Control_Call(scard_call_context* smartcard,
wStream* out,
1492 WINPR_ASSERT(smartcard);
1494 WINPR_ASSERT(operation);
1496 call = &operation->call.control;
1497 ret.pvOutBuffer = (BYTE*)malloc(call->cbOutBufferSize);
1499 if (!ret.pvOutBuffer)
1500 return SCARD_E_NO_MEMORY;
1501 ret.cbOutBufferSize = call->cbOutBufferSize;
1504 wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
1505 call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
1506 scard_log_status_error_wlog(smartcard->log,
"SCardControl", ret.ReturnCode);
1507 status = smartcard_pack_control_return(out, &ret);
1509 free(ret.pvOutBuffer);
1510 if (status != SCARD_S_SUCCESS)
1512 return ret.ReturnCode;
1515WINPR_ATTR_NODISCARD
static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard,
1519 BOOL autoAllocate = FALSE;
1521 DWORD cbAttrLen = 0;
1522 LPBYTE pbAttr =
nullptr;
1526 WINPR_ASSERT(smartcard);
1527 WINPR_ASSERT(operation);
1529 call = &operation->call.getAttrib;
1531 if (!call->fpbAttrIsNULL)
1533 autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE);
1534 cbAttrLen = call->cbAttrLen;
1535 if (cbAttrLen && !autoAllocate)
1537 ret.pbAttr = (BYTE*)malloc(cbAttrLen);
1540 return SCARD_E_NO_MEMORY;
1543 pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
1547 wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
1548 scard_log_status_error_wlog(smartcard->log,
"SCardGetAttrib", ret.ReturnCode);
1549 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cbAttrLen == SCARD_AUTOALLOCATE))
1550 return SCARD_F_UNKNOWN_ERROR;
1552 ret.cbAttrLen = cbAttrLen;
1554 status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
1557 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
1563WINPR_ATTR_NODISCARD
static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard,
1564 WINPR_ATTR_UNUSED
wStream* out,
1570 WINPR_ASSERT(smartcard);
1572 WINPR_ASSERT(operation);
1574 call = &operation->call.setAttrib;
1576 ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
1578 scard_log_status_error_wlog(smartcard->log,
"SCardSetAttrib", ret.ReturnCode);
1579 smartcard_trace_long_return_int(smartcard->log, &ret,
"SetAttrib");
1581 return ret.ReturnCode;
1584WINPR_ATTR_NODISCARD
static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard,
1585 WINPR_ATTR_UNUSED
wStream* out,
1588 LONG status = SCARD_S_SUCCESS;
1590 WINPR_ASSERT(smartcard);
1592 WINPR_UNUSED(operation);
1594 if (!smartcard->StartedEvent)
1595 smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
1597 if (!smartcard->StartedEvent)
1598 status = SCARD_E_NO_SERVICE;
1603WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard,
1607 LONG status = SCARD_E_INVALID_HANDLE;
1610 WINPR_ASSERT(smartcard);
1611 WINPR_ASSERT(operation);
1618 return STATUS_NO_MEMORY;
1620 for (UINT32 i = 0; i < call->cReaders; i++)
1625 state->szReader = cstate->szReader;
1626 state->dwCurrentState = cstate->dwCurrentState;
1627 state->dwEventState = cstate->dwEventState;
1628 state->cbAtr = cstate->cbAtr;
1630 if (state->cbAtr >
sizeof(state->rgbAtr))
1632 WLog_WARN(SCARD_TAG,
"[%" PRIu32
"] val->cbAtr=%" PRIu32
", max=%" PRIuz, i,
1633 state->cbAtr,
sizeof(state->rgbAtr));
1636 CopyMemory(&(state->rgbAtr), &(cstate->rgbAtr),
sizeof(cstate->rgbAtr));
1639 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1640 0x000001F4, states, call->cReaders);
1642 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", status);
1643 for (UINT32 i = 0; i < call->cAtrs; i++)
1645 for (UINT32 j = 0; j < call->cReaders; j++)
1648 for (UINT32 k = 0; k < mask->cbAtr; k++)
1650 if ((mask->rgbAtr[k] & mask->rgbMask[k]) !=
1651 (states[j].rgbAtr[k] & mask->rgbMask[k]))
1656 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1661 ret.rgReaderStates =
nullptr;
1663 if (call->cReaders > 0)
1664 ret.rgReaderStates =
1667 if (!ret.rgReaderStates)
1669 status = STATUS_NO_MEMORY;
1673 ret.cReaders = call->cReaders;
1675 status = SCARD_E_INVALID_ATR;
1676 for (UINT32 i = 0; i < ret.cReaders; i++)
1681 cur->dwCurrentState = state->dwCurrentState;
1682 cur->dwEventState = state->dwEventState;
1683 cur->cbAtr = state->cbAtr;
1684 CopyMemory(&(cur->rgbAtr), &(state->rgbAtr),
sizeof(cur->rgbAtr));
1686 if (!smartcard_reader_state_return_is_valid(i, cur))
1690 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1694 free(ret.rgReaderStates);
1695 if (status != SCARD_S_SUCCESS)
1697 return ret.ReturnCode;
1700WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsByATRW_Call(scard_call_context* smartcard,
1704 LONG status = SCARD_E_INVALID_HANDLE;
1707 WINPR_ASSERT(smartcard);
1708 WINPR_ASSERT(operation);
1715 return STATUS_NO_MEMORY;
1717 for (UINT32 i = 0; i < call->cReaders; i++)
1722 state->szReader = cstate->szReader;
1723 state->dwCurrentState = cstate->dwCurrentState;
1724 state->dwEventState = cstate->dwEventState;
1725 state->cbAtr = cstate->cbAtr;
1727 if (state->cbAtr >
sizeof(state->rgbAtr))
1729 WLog_WARN(SCARD_TAG,
"[%" PRIu32
"] val->cbAtr=%" PRIu32
", max=%" PRIuz, i,
1730 state->cbAtr,
sizeof(state->rgbAtr));
1733 CopyMemory(&(state->rgbAtr), &(cstate->rgbAtr),
sizeof(cstate->rgbAtr));
1736 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
1737 0x000001F4, states, call->cReaders);
1739 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeW", status);
1740 for (UINT32 i = 0; i < call->cAtrs; i++)
1742 for (UINT32 j = 0; j < call->cReaders; j++)
1745 for (UINT32 k = 0; k < mask->cbAtr; k++)
1747 if ((mask->rgbAtr[k] & mask->rgbMask[k]) !=
1748 (states[j].rgbAtr[k] & mask->rgbMask[k]))
1753 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1758 ret.rgReaderStates =
nullptr;
1760 if (call->cReaders > 0)
1761 ret.rgReaderStates =
1764 if (!ret.rgReaderStates)
1766 status = STATUS_NO_MEMORY;
1770 ret.cReaders = call->cReaders;
1772 status = SCARD_E_INVALID_ATR;
1773 for (UINT32 i = 0; i < ret.cReaders; i++)
1778 cur->dwCurrentState = state->dwCurrentState;
1779 cur->dwEventState = state->dwEventState;
1780 cur->cbAtr = state->cbAtr;
1781 CopyMemory(&(cur->rgbAtr), &(state->rgbAtr),
sizeof(cur->rgbAtr));
1783 if (!smartcard_reader_state_return_is_valid(i, cur))
1787 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1791 free(ret.rgReaderStates);
1792 if (status != SCARD_S_SUCCESS)
1794 return ret.ReturnCode;
1797LONG smartcard_irp_device_control_call(scard_call_context* ctx,
wStream* out, NTSTATUS* pIoStatus,
1802 size_t objectBufferLength = 0;
1806 WINPR_ASSERT(pIoStatus);
1807 WINPR_ASSERT(operation);
1809 const UINT32 ioControlCode = operation->ioControlCode;
1817 const size_t outMaxLen = MAX(2048, operation->outputBufferLength);
1818 if (!Stream_EnsureRemainingCapacity(out, outMaxLen))
1819 return SCARD_E_NO_MEMORY;
1822 Stream_Write_UINT32(out, 0);
1823 Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH);
1824 Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH);
1825 Stream_Write_UINT32(out, 0);
1828 switch (ioControlCode)
1830 case SCARD_IOCTL_ESTABLISHCONTEXT:
1831 result = smartcard_EstablishContext_Call(ctx, out, operation);
1834 case SCARD_IOCTL_RELEASECONTEXT:
1835 result = smartcard_ReleaseContext_Call(ctx, out, operation);
1838 case SCARD_IOCTL_ISVALIDCONTEXT:
1839 result = smartcard_IsValidContext_Call(ctx, out, operation);
1842 case SCARD_IOCTL_LISTREADERGROUPSA:
1843 result = smartcard_ListReaderGroupsA_Call(ctx, out, operation);
1846 case SCARD_IOCTL_LISTREADERGROUPSW:
1847 result = smartcard_ListReaderGroupsW_Call(ctx, out, operation);
1850 case SCARD_IOCTL_LISTREADERSA:
1851 result = smartcard_ListReadersA_Call(ctx, out, operation);
1854 case SCARD_IOCTL_LISTREADERSW:
1855 result = smartcard_ListReadersW_Call(ctx, out, operation);
1858 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1859 result = smartcard_IntroduceReaderGroupA_Call(ctx, out, operation);
1862 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1863 result = smartcard_IntroduceReaderGroupW_Call(ctx, out, operation);
1866 case SCARD_IOCTL_FORGETREADERGROUPA:
1867 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
1870 case SCARD_IOCTL_FORGETREADERGROUPW:
1871 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
1874 case SCARD_IOCTL_INTRODUCEREADERA:
1875 result = smartcard_IntroduceReaderA_Call(ctx, out, operation);
1878 case SCARD_IOCTL_INTRODUCEREADERW:
1879 result = smartcard_IntroduceReaderW_Call(ctx, out, operation);
1882 case SCARD_IOCTL_FORGETREADERA:
1883 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
1886 case SCARD_IOCTL_FORGETREADERW:
1887 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
1890 case SCARD_IOCTL_ADDREADERTOGROUPA:
1891 result = smartcard_AddReaderToGroupA_Call(ctx, out, operation);
1894 case SCARD_IOCTL_ADDREADERTOGROUPW:
1895 result = smartcard_AddReaderToGroupW_Call(ctx, out, operation);
1898 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1899 result = smartcard_RemoveReaderFromGroupA_Call(ctx, out, operation);
1902 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1903 result = smartcard_RemoveReaderFromGroupW_Call(ctx, out, operation);
1906 case SCARD_IOCTL_LOCATECARDSA:
1907 result = smartcard_LocateCardsA_Call(ctx, out, operation);
1910 case SCARD_IOCTL_LOCATECARDSW:
1911 result = smartcard_LocateCardsW_Call(ctx, out, operation);
1914 case SCARD_IOCTL_GETSTATUSCHANGEA:
1915 result = smartcard_GetStatusChangeA_Call(ctx, out, operation);
1918 case SCARD_IOCTL_GETSTATUSCHANGEW:
1919 result = smartcard_GetStatusChangeW_Call(ctx, out, operation);
1922 case SCARD_IOCTL_CANCEL:
1923 result = smartcard_Cancel_Call(ctx, out, operation);
1926 case SCARD_IOCTL_CONNECTA:
1927 result = smartcard_ConnectA_Call(ctx, out, operation);
1930 case SCARD_IOCTL_CONNECTW:
1931 result = smartcard_ConnectW_Call(ctx, out, operation);
1934 case SCARD_IOCTL_RECONNECT:
1935 result = smartcard_Reconnect_Call(ctx, out, operation);
1938 case SCARD_IOCTL_DISCONNECT:
1939 result = smartcard_Disconnect_Call(ctx, out, operation);
1942 case SCARD_IOCTL_BEGINTRANSACTION:
1943 result = smartcard_BeginTransaction_Call(ctx, out, operation);
1946 case SCARD_IOCTL_ENDTRANSACTION:
1947 result = smartcard_EndTransaction_Call(ctx, out, operation);
1950 case SCARD_IOCTL_STATE:
1951 result = smartcard_State_Call(ctx, out, operation);
1954 case SCARD_IOCTL_STATUSA:
1955 result = smartcard_StatusA_Call(ctx, out, operation);
1958 case SCARD_IOCTL_STATUSW:
1959 result = smartcard_StatusW_Call(ctx, out, operation);
1962 case SCARD_IOCTL_TRANSMIT:
1963 result = smartcard_Transmit_Call(ctx, out, operation);
1966 case SCARD_IOCTL_CONTROL:
1967 result = smartcard_Control_Call(ctx, out, operation);
1970 case SCARD_IOCTL_GETATTRIB:
1971 result = smartcard_GetAttrib_Call(ctx, out, operation);
1974 case SCARD_IOCTL_SETATTRIB:
1975 result = smartcard_SetAttrib_Call(ctx, out, operation);
1978 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
1979 result = smartcard_AccessStartedEvent_Call(ctx, out, operation);
1982 case SCARD_IOCTL_LOCATECARDSBYATRA:
1983 result = smartcard_LocateCardsByATRA_Call(ctx, out, operation);
1986 case SCARD_IOCTL_LOCATECARDSBYATRW:
1987 result = smartcard_LocateCardsByATRW_Call(ctx, out, operation);
1990 case SCARD_IOCTL_READCACHEA:
1991 result = smartcard_ReadCacheA_Call(ctx, out, operation);
1994 case SCARD_IOCTL_READCACHEW:
1995 result = smartcard_ReadCacheW_Call(ctx, out, operation);
1998 case SCARD_IOCTL_WRITECACHEA:
1999 result = smartcard_WriteCacheA_Call(ctx, out, operation);
2002 case SCARD_IOCTL_WRITECACHEW:
2003 result = smartcard_WriteCacheW_Call(ctx, out, operation);
2006 case SCARD_IOCTL_GETTRANSMITCOUNT:
2007 result = smartcard_GetTransmitCount_Call(ctx, out, operation);
2010 case SCARD_IOCTL_RELEASETARTEDEVENT:
2011 result = smartcard_ReleaseStartedEvent_Call(ctx, out, operation);
2014 case SCARD_IOCTL_GETREADERICON:
2015 result = smartcard_GetReaderIcon_Call(ctx, out, operation);
2018 case SCARD_IOCTL_GETDEVICETYPEID:
2019 result = smartcard_GetDeviceTypeId_Call(ctx, out, operation);
2023 result = STATUS_UNSUCCESSFUL;
2033 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
2034 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
2036 offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
2037 const LONG rc = smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
2038 if (rc != SCARD_S_SUCCESS)
2042 if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
2043 (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
2044 (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
2046 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
2047 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
2050 *pIoStatus = STATUS_SUCCESS;
2052 if ((result & 0xC0000000L) == 0xC0000000L)
2055 *pIoStatus = result;
2057 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
2058 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
2061 Stream_SealLength(out);
2062 size_t outputBufferLength = Stream_Length(out);
2063 size_t dataEndPos = outputBufferLength;
2065 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
2066 outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
2067 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
2068 objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
2069 WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
2070 WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
2071 if (!Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH))
2072 return SCARD_E_BAD_SEEK;
2081 if (outputBufferLength > operation->outputBufferLength)
2083 WLog_Print(ctx->log, WLOG_DEBUG,
2084 "IRP warn: expected outputBufferLength %" PRIuz
", but current limit %" PRIu32
2085 ", respond with STATUS_BUFFER_TOO_SMALL for retransmit with larger buffer",
2086 outputBufferLength, operation->outputBufferLength);
2088 *pIoStatus = STATUS_BUFFER_TOO_SMALL;
2089 result = *pIoStatus;
2090 outputBufferLength = 0;
2091 objectBufferLength = 0;
2095 WLog_Print(ctx->log, WLOG_TRACE,
"IRP trace: outputBufferLength %" PRIuz
", limit %" PRIu32,
2096 outputBufferLength, operation->outputBufferLength);
2100 Stream_Write_UINT32(out, (UINT32)outputBufferLength);
2101 smartcard_pack_common_type_header(out);
2102 smartcard_pack_private_type_header(
2103 out, (UINT32)objectBufferLength);
2104 Stream_Write_INT32(out, result);
2105 if (result == STATUS_BUFFER_TOO_SMALL)
2106 Stream_SealLength(out);
2107 else if (!Stream_SetPosition(out, dataEndPos))
2108 return SCARD_E_BAD_SEEK;
2109 return SCARD_S_SUCCESS;
2112void context_free(
void* arg)
2114 struct s_scard_context_element* element = arg;
2118 if (element->fn_free)
2119 element->fn_free(element->context);
2123#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
2124scard_call_context* smartcard_call_context_new(
const rdpSettings* settings)
2127 if (!inst || !inst->context)
2129 return smartcard_call_context_new_with_context(inst->context);
2133scard_call_context* smartcard_call_context_new_with_context(rdpContext* context)
2135 WINPR_ASSERT(context);
2136 scard_call_context* ctx = calloc(1,
sizeof(scard_call_context));
2140 ctx->context = context;
2142 const rdpSettings* settings = context->settings;
2143 WINPR_ASSERT(settings);
2145 ctx->log = WLog_Get(SCARD_TAG);
2146 WINPR_ASSERT(ctx->log);
2148 ctx->stopEvent = CreateEventA(
nullptr, TRUE, FALSE,
nullptr);
2149 if (!ctx->stopEvent)
2152 ctx->names = LinkedList_New();
2156#if defined(WITH_SMARTCARD_EMULATE)
2160 if (ctx->useEmulatedCard)
2162#if defined(WITH_SMARTCARD_EMULATE)
2163 ctx->emulation = Emulate_New(settings);
2164 if (!ctx->emulation)
2167 WLog_Print(ctx->log, WLOG_ERROR,
"Smartcard emulation requested, but not supported!");
2176 ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
2178 if (!ctx->hWinSCardLibrary)
2180 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard library: '%s'",
2185 if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
2187 ctx->pWinSCardApi = &ctx->WinSCardApi;
2191 ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
2194 if (!ctx->pWinSCardApi)
2196 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard API!");
2201 ctx->rgSCardContextList = HashTable_New(FALSE);
2202 if (!ctx->rgSCardContextList)
2206 wObject* obj = HashTable_ValueObject(ctx->rgSCardContextList);
2213 WINPR_PRAGMA_DIAG_PUSH
2214 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2215 smartcard_call_context_free(ctx);
2216 WINPR_PRAGMA_DIAG_POP
2220void smartcard_call_context_free(scard_call_context* ctx)
2225 smartcard_call_context_signal_stop(ctx, FALSE);
2227 LinkedList_Free(ctx->names);
2228 if (ctx->StartedEvent)
2230 WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
2231 wrap_raw(ctx, SCardReleaseStartedEvent);
2234 if (ctx->useEmulatedCard)
2236#ifdef WITH_SMARTCARD_EMULATE
2239 Emulate_Free(ctx->emulation);
2240 ctx->emulation =
nullptr;
2245 if (ctx->hWinSCardLibrary)
2248 FreeLibrary(ctx->hWinSCardLibrary);
2249 ctx->hWinSCardLibrary =
nullptr;
2252 ctx->pWinSCardApi =
nullptr;
2254 HashTable_Free(ctx->rgSCardContextList);
2255 (void)CloseHandle(ctx->stopEvent);
2259BOOL smartcard_call_context_add(scard_call_context* ctx,
const char* name)
2263 return LinkedList_AddLast(ctx->names, name);
2266BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2269 if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
2271 wrap(ctx, SCardCancel, hContext);
2276BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2279 wrap(ctx, SCardReleaseContext, hContext);
2283BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
2288 HashTable_Clear(ctx->rgSCardContextList);
2292BOOL smarcard_call_set_callbacks(scard_call_context* ctx,
void* userdata,
2293 void* (*fn_new)(
void*, SCARDCONTEXT),
void (*fn_free)(
void*))
2296 ctx->userdata = userdata;
2297 ctx->fn_new = fn_new;
2298 ctx->fn_free = fn_free;
2302void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2304 struct s_scard_context_element* element =
nullptr;
2307 element = HashTable_GetItemValue(ctx->rgSCardContextList, (
void*)hContext);
2310 return element->context;
2313BOOL smartcard_call_is_configured(scard_call_context* ctx)
2317#if defined(WITH_SMARTCARD_EMULATE)
2318 if (ctx->useEmulatedCard)
2319 return Emulate_IsConfigured(ctx->emulation);
2325BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
2329 if (!ctx->stopEvent)
2333 return ResetEvent(ctx->stopEvent);
2335 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