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);
105static LONG smartcard_EstablishContext_Call(scard_call_context* smartcard,
wStream* out,
108 SCARDCONTEXT hContext = WINPR_C_ARRAY_INIT;
111 LONG status = ret.ReturnCode =
112 wrap(smartcard, SCardEstablishContext, call->dwScope,
nullptr,
nullptr, &hContext);
114 if (ret.ReturnCode == SCARD_S_SUCCESS)
116 const void* key = (
void*)(
size_t)hContext;
117 struct s_scard_context_element* pContext =
118 calloc(1,
sizeof(
struct s_scard_context_element));
120 return STATUS_NO_MEMORY;
122 pContext->fn_free = smartcard->fn_free;
124 if (smartcard->fn_new)
126 pContext->context = smartcard->fn_new(smartcard->userdata, hContext);
127 if (!pContext->context)
130 return STATUS_NO_MEMORY;
134 if (!HashTable_Insert(smartcard->rgSCardContextList, key, (
void*)pContext))
136 WLog_Print(smartcard->log, WLOG_ERROR,
"HashTable_Insert failed!");
137 context_free(pContext);
138 return STATUS_INTERNAL_ERROR;
143 return scard_log_status_error_wlog(smartcard->log,
"SCardEstablishContext", status);
147 smartcard_scard_context_native_to_redir(&(ret.hContext), hContext);
149 status = smartcard_pack_establish_context_return(out, &ret);
150 if (status != SCARD_S_SUCCESS)
152 return scard_log_status_error_wlog(smartcard->log,
153 "smartcard_pack_establish_context_return", status);
156 return ret.ReturnCode;
159static LONG smartcard_ReleaseContext_Call(scard_call_context* smartcard,
160 WINPR_ATTR_UNUSED
wStream* out,
165 WINPR_ASSERT(smartcard);
167 WINPR_ASSERT(operation);
169 ret.ReturnCode = wrap(smartcard, SCardReleaseContext, operation->hContext);
171 if (ret.ReturnCode == SCARD_S_SUCCESS)
172 HashTable_Remove(smartcard->rgSCardContextList, (
void*)operation->hContext);
175 return scard_log_status_error_wlog(smartcard->log,
"SCardReleaseContext", ret.ReturnCode);
178 smartcard_trace_long_return_int(smartcard->log, &ret,
"ReleaseContext");
179 return ret.ReturnCode;
182static LONG smartcard_IsValidContext_Call(scard_call_context* smartcard,
183 WINPR_ATTR_UNUSED
wStream* out,
188 WINPR_ASSERT(smartcard);
190 WINPR_ASSERT(operation);
192 ret.ReturnCode = wrap(smartcard, SCardIsValidContext, operation->hContext);
193 smartcard_trace_long_return_int(smartcard->log, &ret,
"IsValidContext");
194 return ret.ReturnCode;
197static LONG smartcard_ListReaderGroupsA_Call(scard_call_context* smartcard,
wStream* out,
202 LPSTR mszGroups =
nullptr;
205 WINPR_ASSERT(smartcard);
207 WINPR_ASSERT(operation);
209 cchGroups = SCARD_AUTOALLOCATE;
211 wrap(smartcard, SCardListReaderGroupsA, operation->hContext, (LPSTR)&mszGroups, &cchGroups);
212 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchGroups == SCARD_AUTOALLOCATE))
213 return SCARD_F_UNKNOWN_ERROR;
215 ret.msz = (BYTE*)mszGroups;
216 ret.cBytes = cchGroups;
218 status = smartcard_pack_list_reader_groups_return(out, &ret, FALSE);
220 if (status != SCARD_S_SUCCESS)
224 wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
226 return ret.ReturnCode;
229static LONG smartcard_ListReaderGroupsW_Call(scard_call_context* smartcard,
wStream* out,
234 LPWSTR mszGroups =
nullptr;
237 WINPR_ASSERT(smartcard);
239 WINPR_ASSERT(operation);
241 cchGroups = SCARD_AUTOALLOCATE;
242 status = ret.ReturnCode = wrap(smartcard, SCardListReaderGroupsW, operation->hContext,
243 (LPWSTR)&mszGroups, &cchGroups);
244 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchGroups == SCARD_AUTOALLOCATE))
245 return SCARD_F_UNKNOWN_ERROR;
247 ret.msz = (BYTE*)mszGroups;
249 WINPR_ASSERT(cchGroups < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
250 const size_t blen =
sizeof(WCHAR) * cchGroups;
251 WINPR_ASSERT(blen <= UINT32_MAX);
252 ret.cBytes = (UINT32)blen;
254 if (status != SCARD_S_SUCCESS)
257 status = smartcard_pack_list_reader_groups_return(out, &ret, TRUE);
259 if (status != SCARD_S_SUCCESS)
263 wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
265 return ret.ReturnCode;
268static BOOL filter_match(wLinkedList* list, LPCSTR reader,
size_t readerLen)
273 LinkedList_Enumerator_Reset(list);
275 while (LinkedList_Enumerator_MoveNext(list))
277 const char* filter = LinkedList_Enumerator_Current(list);
281 if (strstr(reader, filter) !=
nullptr)
289static DWORD filter_device_by_name_a(wLinkedList* list, LPSTR* mszReaders, DWORD cchReaders)
294 if (*mszReaders ==
nullptr || LinkedList_Count(list) < 1)
299 LPCSTR rreader = &(*mszReaders)[rpos];
300 LPSTR wreader = &(*mszReaders)[wpos];
301 size_t readerLen = strnlen(rreader, cchReaders - rpos);
303 rpos += readerLen + 1;
305 if (filter_match(list, rreader, readerLen))
307 if (rreader != wreader)
308 memmove(wreader, rreader, readerLen + 1);
310 wpos += readerLen + 1;
312 }
while (rpos < cchReaders);
317 if (wpos >= cchReaders)
320 (*mszReaders)[wpos++] =
'\0';
326static DWORD filter_device_by_name_w(wLinkedList* list, LPWSTR* mszReaders, DWORD cchReaders)
329 LPSTR readers =
nullptr;
331 if (LinkedList_Count(list) < 1)
334 readers = ConvertMszWCharNToUtf8Alloc(*mszReaders, cchReaders,
nullptr);
342 *mszReaders =
nullptr;
343 rc = filter_device_by_name_a(list, &readers, cchReaders);
345 *mszReaders = ConvertMszUtf8NToWCharAlloc(readers, rc,
nullptr);
353static LONG smartcard_ListReadersA_Call(scard_call_context* smartcard,
wStream* out,
357 LPSTR mszReaders =
nullptr;
359 WINPR_ASSERT(smartcard);
361 WINPR_ASSERT(operation);
364 DWORD cchReaders = SCARD_AUTOALLOCATE;
365 LONG status = ret.ReturnCode = wrap(smartcard, SCardListReadersA, operation->hContext,
366 (LPCSTR)call->mszGroups, (LPSTR)&mszReaders, &cchReaders);
367 if (status == SCARD_S_SUCCESS)
369 if (cchReaders == SCARD_AUTOALLOCATE)
370 status = SCARD_F_UNKNOWN_ERROR;
373 if (status != SCARD_S_SUCCESS)
375 (void)scard_log_status_error_wlog(smartcard->log,
"SCardListReadersA", status);
376 return smartcard_pack_list_readers_return(out, &ret, FALSE);
379 void* original = mszReaders;
380 cchReaders = filter_device_by_name_a(smartcard->names, &mszReaders, cchReaders);
381 ret.msz = (BYTE*)mszReaders;
382 ret.cBytes = cchReaders;
384 status = smartcard_pack_list_readers_return(out, &ret, FALSE);
386 wrap(smartcard, SCardFreeMemory, operation->hContext, original);
388 if (status != SCARD_S_SUCCESS)
389 return scard_log_status_error_wlog(smartcard->log,
"smartcard_pack_list_readers_return",
392 return ret.ReturnCode;
395static LONG smartcard_ListReadersW_Call(scard_call_context* smartcard,
wStream* out,
400 DWORD cchReaders = 0;
416 WINPR_ASSERT(smartcard);
417 WINPR_ASSERT(operation);
419 call = &operation->call.listReaders;
421 string.bp = call->mszGroups;
422 cchReaders = SCARD_AUTOALLOCATE;
423 status = ret.ReturnCode = wrap(smartcard, SCardListReadersW, operation->hContext,
string.wz,
424 (LPWSTR)&mszReaders.pw, &cchReaders);
425 if (status == SCARD_S_SUCCESS)
427 if (cchReaders == SCARD_AUTOALLOCATE)
428 status = SCARD_F_UNKNOWN_ERROR;
431 if (status != SCARD_S_SUCCESS)
433 (void)scard_log_status_error_wlog(smartcard->log,
"SCardListReadersW", status);
434 return smartcard_pack_list_readers_return(out, &ret, TRUE);
437 void* original = mszReaders.pb;
438 cchReaders = filter_device_by_name_w(smartcard->names, &mszReaders.pw, cchReaders);
439 ret.msz = mszReaders.pb;
440 ret.cBytes = cchReaders *
sizeof(WCHAR);
441 status = smartcard_pack_list_readers_return(out, &ret, TRUE);
444 wrap(smartcard, SCardFreeMemory, operation->hContext, original);
446 if (status != SCARD_S_SUCCESS)
449 return ret.ReturnCode;
452static LONG smartcard_IntroduceReaderGroupA_Call(scard_call_context* smartcard,
453 WINPR_ATTR_UNUSED
wStream* out,
459 WINPR_ASSERT(smartcard);
461 WINPR_ASSERT(operation);
463 call = &operation->call.contextAndStringA;
464 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupA, operation->hContext, call->sz);
465 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderGroupA", ret.ReturnCode);
466 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderGroupA");
467 return ret.ReturnCode;
470static LONG smartcard_IntroduceReaderGroupW_Call(scard_call_context* smartcard,
471 WINPR_ATTR_UNUSED
wStream* out,
477 WINPR_ASSERT(smartcard);
479 WINPR_ASSERT(operation);
481 call = &operation->call.contextAndStringW;
482 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupW, operation->hContext, call->sz);
483 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderGroupW", ret.ReturnCode);
484 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderGroupW");
485 return ret.ReturnCode;
488static LONG smartcard_IntroduceReaderA_Call(scard_call_context* smartcard,
489 WINPR_ATTR_UNUSED
wStream* out,
495 WINPR_ASSERT(smartcard);
497 WINPR_ASSERT(operation);
499 call = &operation->call.contextAndTwoStringA;
501 wrap(smartcard, SCardIntroduceReaderA, operation->hContext, call->sz1, call->sz2);
502 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderA", ret.ReturnCode);
503 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderA");
504 return ret.ReturnCode;
507static LONG smartcard_IntroduceReaderW_Call(scard_call_context* smartcard,
508 WINPR_ATTR_UNUSED
wStream* out,
514 WINPR_ASSERT(smartcard);
516 WINPR_ASSERT(operation);
518 call = &operation->call.contextAndTwoStringW;
520 wrap(smartcard, SCardIntroduceReaderW, operation->hContext, call->sz1, call->sz2);
521 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderW", ret.ReturnCode);
522 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderW");
523 return ret.ReturnCode;
526static LONG smartcard_ForgetReaderA_Call(scard_call_context* smartcard,
527 WINPR_ATTR_UNUSED
wStream* out,
533 WINPR_ASSERT(smartcard);
535 WINPR_ASSERT(operation);
537 call = &operation->call.contextAndStringA;
538 ret.ReturnCode = wrap(smartcard, SCardForgetReaderA, operation->hContext, call->sz);
539 scard_log_status_error_wlog(smartcard->log,
"SCardForgetReaderA", ret.ReturnCode);
540 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardForgetReaderA");
541 return ret.ReturnCode;
544static LONG smartcard_ForgetReaderW_Call(scard_call_context* smartcard,
545 WINPR_ATTR_UNUSED
wStream* out,
551 WINPR_ASSERT(smartcard);
553 WINPR_ASSERT(operation);
555 call = &operation->call.contextAndStringW;
556 ret.ReturnCode = wrap(smartcard, SCardForgetReaderW, operation->hContext, call->sz);
557 scard_log_status_error_wlog(smartcard->log,
"SCardForgetReaderW", ret.ReturnCode);
558 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardForgetReaderW");
559 return ret.ReturnCode;
562static LONG smartcard_AddReaderToGroupA_Call(scard_call_context* smartcard,
563 WINPR_ATTR_UNUSED
wStream* out,
569 WINPR_ASSERT(smartcard);
571 WINPR_ASSERT(operation);
573 call = &operation->call.contextAndTwoStringA;
575 wrap(smartcard, SCardAddReaderToGroupA, operation->hContext, call->sz1, call->sz2);
576 scard_log_status_error_wlog(smartcard->log,
"SCardAddReaderToGroupA", ret.ReturnCode);
577 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardAddReaderToGroupA");
578 return ret.ReturnCode;
581static LONG smartcard_AddReaderToGroupW_Call(scard_call_context* smartcard,
582 WINPR_ATTR_UNUSED
wStream* out,
588 WINPR_ASSERT(smartcard);
590 WINPR_ASSERT(operation);
592 call = &operation->call.contextAndTwoStringW;
594 wrap(smartcard, SCardAddReaderToGroupW, operation->hContext, call->sz1, call->sz2);
595 scard_log_status_error_wlog(smartcard->log,
"SCardAddReaderToGroupW", ret.ReturnCode);
596 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardAddReaderToGroupA");
597 return ret.ReturnCode;
600static LONG smartcard_RemoveReaderFromGroupA_Call(scard_call_context* smartcard,
601 WINPR_ATTR_UNUSED
wStream* out,
607 WINPR_ASSERT(smartcard);
609 WINPR_ASSERT(operation);
611 call = &operation->call.contextAndTwoStringA;
613 wrap(smartcard, SCardRemoveReaderFromGroupA, operation->hContext, call->sz1, call->sz2);
614 scard_log_status_error_wlog(smartcard->log,
"SCardRemoveReaderFromGroupA", ret.ReturnCode);
615 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardRemoveReaderFromGroupA");
616 return ret.ReturnCode;
619static LONG smartcard_RemoveReaderFromGroupW_Call(scard_call_context* smartcard,
620 WINPR_ATTR_UNUSED
wStream* out,
626 WINPR_ASSERT(smartcard);
628 WINPR_ASSERT(operation);
630 call = &operation->call.contextAndTwoStringW;
632 wrap(smartcard, SCardRemoveReaderFromGroupW, operation->hContext, call->sz1, call->sz2);
633 scard_log_status_error_wlog(smartcard->log,
"SCardRemoveReaderFromGroupW", ret.ReturnCode);
634 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardRemoveReaderFromGroupW");
635 return ret.ReturnCode;
638static LONG smartcard_LocateCardsA_Call(scard_call_context* smartcard,
wStream* out,
645 WINPR_ASSERT(smartcard);
646 WINPR_ASSERT(operation);
648 call = &operation->call.locateCardsA;
650 ret.ReturnCode = wrap(smartcard, SCardLocateCardsA, operation->hContext, call->mszCards,
651 call->rgReaderStates, call->cReaders);
652 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsA", ret.ReturnCode);
653 ret.rgReaderStates =
nullptr;
655 if (call->cReaders > 0)
660 if (!ret.rgReaderStates)
661 return STATUS_NO_MEMORY;
662 ret.cReaders = call->cReaders;
665 for (UINT32 x = 0; x < ret.cReaders; x++)
667 ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
668 ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
669 ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
670 CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
671 sizeof(ret.rgReaderStates[x].rgbAtr));
674 status = smartcard_pack_locate_cards_return(out, &ret);
676 if (status != SCARD_S_SUCCESS)
679 return ret.ReturnCode;
682static LONG smartcard_LocateCardsW_Call(scard_call_context* smartcard,
wStream* out,
689 WINPR_ASSERT(smartcard);
690 WINPR_ASSERT(operation);
692 call = &operation->call.locateCardsW;
694 ret.ReturnCode = wrap(smartcard, SCardLocateCardsW, operation->hContext, call->mszCards,
695 call->rgReaderStates, call->cReaders);
696 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsW", ret.ReturnCode);
697 ret.rgReaderStates =
nullptr;
699 if (call->cReaders > 0)
704 if (!ret.rgReaderStates)
705 return STATUS_NO_MEMORY;
706 ret.cReaders = call->cReaders;
709 for (UINT32 x = 0; x < ret.cReaders; x++)
711 ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
712 ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
713 ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
714 CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
715 sizeof(ret.rgReaderStates[x].rgbAtr));
718 status = smartcard_pack_locate_cards_return(out, &ret);
720 if (status != SCARD_S_SUCCESS)
723 return ret.ReturnCode;
726static LONG smartcard_ReadCacheA_Call(scard_call_context* smartcard,
wStream* out,
734 WINPR_ASSERT(smartcard);
736 WINPR_ASSERT(operation);
738 call = &operation->call.readCacheA;
739 autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE);
741 if (!call->Common.fPbDataIsNULL)
745 ret.pbData = malloc(call->Common.cbDataLen);
747 return SCARD_F_INTERNAL_ERROR;
749 ret.cbDataLen = call->Common.cbDataLen;
753 ret.ReturnCode = wrap(smartcard, SCardReadCacheA, operation->hContext,
754 call->Common.CardIdentifier, call->Common.FreshnessCounter,
755 call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
758 wrap(smartcard, SCardReadCacheA, operation->hContext, call->Common.CardIdentifier,
759 call->Common.FreshnessCounter, call->szLookupName, ret.pbData, &ret.cbDataLen);
761 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, call->szLookupName,
764 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
765 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
767 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheA", ret.ReturnCode);
770 status = smartcard_pack_read_cache_return(out, &ret);
772 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
775 if (status != SCARD_S_SUCCESS)
778 return ret.ReturnCode;
781static LONG smartcard_ReadCacheW_Call(scard_call_context* smartcard,
wStream* out,
788 WINPR_ASSERT(smartcard);
790 WINPR_ASSERT(operation);
792 call = &operation->call.readCacheW;
794 if (!call->Common.fPbDataIsNULL)
795 ret.cbDataLen = SCARD_AUTOALLOCATE;
798 wrap(smartcard, SCardReadCacheW, operation->hContext, call->Common.CardIdentifier,
799 call->Common.FreshnessCounter, call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
801 if (WLog_IsLevelActive(smartcard->log, WLOG_TRACE))
803 char buffer[128] = WINPR_C_ARRAY_INIT;
804 (void)ConvertWCharToUtf8(call->szLookupName, buffer,
sizeof(buffer));
805 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, buffer, ret.cbDataLen);
807 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
808 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
810 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheW", ret.ReturnCode);
813 status = smartcard_pack_read_cache_return(out, &ret);
815 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
817 if (status != SCARD_S_SUCCESS)
820 return ret.ReturnCode;
823static LONG smartcard_WriteCacheA_Call(scard_call_context* smartcard,
824 WINPR_ATTR_UNUSED
wStream* out,
830 WINPR_ASSERT(smartcard);
832 WINPR_ASSERT(operation);
834 call = &operation->call.writeCacheA;
836 ret.ReturnCode = wrap(smartcard, SCardWriteCacheA, operation->hContext,
837 call->Common.CardIdentifier, call->Common.FreshnessCounter,
838 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
839 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheA", ret.ReturnCode);
840 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheA");
841 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, call->szLookupName,
842 call->Common.cbDataLen);
843 return ret.ReturnCode;
846static LONG smartcard_WriteCacheW_Call(scard_call_context* smartcard,
847 WINPR_ATTR_UNUSED
wStream* out,
853 WINPR_ASSERT(smartcard);
855 WINPR_ASSERT(operation);
857 call = &operation->call.writeCacheW;
859 ret.ReturnCode = wrap(smartcard, SCardWriteCacheW, operation->hContext,
860 call->Common.CardIdentifier, call->Common.FreshnessCounter,
861 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
862 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheW", ret.ReturnCode);
863 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheW");
865 if (WLog_IsLevelActive(smartcard->log, WLOG_TRACE))
867 char buffer[128] = WINPR_C_ARRAY_INIT;
868 (void)ConvertWCharToUtf8(call->szLookupName, buffer,
sizeof(buffer));
869 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, buffer,
870 call->Common.cbDataLen);
872 return ret.ReturnCode;
875static LONG smartcard_GetTransmitCount_Call(scard_call_context* smartcard,
wStream* out,
881 WINPR_ASSERT(smartcard);
883 WINPR_ASSERT(operation);
885 ret.ReturnCode = wrap(smartcard, SCardGetTransmitCount, operation->hCard, &ret.cTransmitCount);
886 scard_log_status_error_wlog(smartcard->log,
"SCardGetTransmitCount", ret.ReturnCode);
887 status = smartcard_pack_get_transmit_count_return(out, &ret);
888 if (status != SCARD_S_SUCCESS)
891 return ret.ReturnCode;
894static LONG smartcard_ReleaseStartedEvent_Call(scard_call_context* smartcard,
wStream* out,
897 WINPR_UNUSED(smartcard);
899 WINPR_UNUSED(operation);
901 WLog_Print(smartcard->log, WLOG_WARN,
902 "According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
903 "this is not supported?!?");
904 return SCARD_E_UNSUPPORTED_FEATURE;
907static LONG smartcard_GetReaderIcon_Call(scard_call_context* smartcard,
wStream* out,
914 WINPR_ASSERT(smartcard);
916 WINPR_ASSERT(operation);
918 call = &operation->call.getReaderIcon;
920 ret.cbDataLen = SCARD_AUTOALLOCATE;
921 ret.ReturnCode = wrap(smartcard, SCardGetReaderIconW, operation->hContext, call->szReaderName,
922 (LPBYTE)&ret.pbData, &ret.cbDataLen);
923 scard_log_status_error_wlog(smartcard->log,
"SCardGetReaderIconW", ret.ReturnCode);
924 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cbDataLen == SCARD_AUTOALLOCATE))
925 return SCARD_F_UNKNOWN_ERROR;
927 status = smartcard_pack_get_reader_icon_return(out, &ret);
928 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
929 if (status != SCARD_S_SUCCESS)
932 return ret.ReturnCode;
935static LONG smartcard_GetDeviceTypeId_Call(scard_call_context* smartcard,
wStream* out,
942 WINPR_ASSERT(smartcard);
944 WINPR_ASSERT(operation);
946 call = &operation->call.getDeviceTypeId;
948 ret.ReturnCode = wrap(smartcard, SCardGetDeviceTypeIdW, operation->hContext, call->szReaderName,
950 scard_log_status_error_wlog(smartcard->log,
"SCardGetDeviceTypeIdW", ret.ReturnCode);
952 status = smartcard_pack_device_type_id_return(out, &ret);
953 if (status != SCARD_S_SUCCESS)
956 return ret.ReturnCode;
959static BOOL smartcard_context_was_aborted(scard_call_context* smartcard)
961 WINPR_ASSERT(smartcard);
963 HANDLE handles[] = { smartcard->stopEvent, freerdp_abort_event(smartcard->context) };
964 const DWORD rc = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, 0);
965 return (rc >= WAIT_OBJECT_0) && (rc <= WAIT_OBJECT_0 + ARRAYSIZE(handles));
968static LONG smartcard_GetStatusChangeA_Call(scard_call_context* smartcard,
wStream* out,
971 LONG status = STATUS_NO_MEMORY;
973 const DWORD dwTimeStep = 100;
978 WINPR_ASSERT(smartcard);
980 WINPR_ASSERT(operation);
982 call = &operation->call.getStatusChangeA;
983 dwTimeOut = call->dwTimeOut;
985 if (call->cReaders > 0)
990 if (!rgReaderStates || !ret.rgReaderStates)
993 ret.cReaders = call->cReaders;
996 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
998 if (call->cReaders > 0)
999 memcpy(rgReaderStates, call->rgReaderStates,
1001 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1002 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
1003 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1005 if (smartcard_context_was_aborted(smartcard))
1007 if (dwTimeOut != INFINITE)
1010 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", ret.ReturnCode);
1012 for (UINT32 index = 0; index < ret.cReaders; index++)
1017 rout->dwCurrentState = cur->dwCurrentState;
1018 rout->dwEventState = cur->dwEventState;
1019 rout->cbAtr = cur->cbAtr;
1020 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1023 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1025 free(ret.rgReaderStates);
1026 free(rgReaderStates);
1027 if (status != SCARD_S_SUCCESS)
1029 return ret.ReturnCode;
1032static LONG smartcard_GetStatusChangeW_Call(scard_call_context* smartcard,
wStream* out,
1035 LONG status = STATUS_NO_MEMORY;
1036 DWORD dwTimeOut = 0;
1037 const DWORD dwTimeStep = 100;
1041 WINPR_ASSERT(smartcard);
1043 WINPR_ASSERT(operation);
1046 dwTimeOut = call->dwTimeOut;
1048 if (call->cReaders > 0)
1051 ret.rgReaderStates =
1053 if (!rgReaderStates || !ret.rgReaderStates)
1056 ret.cReaders = call->cReaders;
1059 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
1061 if (call->cReaders > 0)
1062 memcpy(rgReaderStates, call->rgReaderStates,
1065 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
1066 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
1068 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1070 if (smartcard_context_was_aborted(smartcard))
1072 if (dwTimeOut != INFINITE)
1075 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeW", ret.ReturnCode);
1077 for (UINT32 index = 0; index < ret.cReaders; index++)
1082 rout->dwCurrentState = cur->dwCurrentState;
1083 rout->dwEventState = cur->dwEventState;
1084 rout->cbAtr = cur->cbAtr;
1085 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1088 status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
1090 free(ret.rgReaderStates);
1091 free(rgReaderStates);
1092 if (status != SCARD_S_SUCCESS)
1094 return ret.ReturnCode;
1097static LONG smartcard_Cancel_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1102 WINPR_ASSERT(smartcard);
1104 WINPR_ASSERT(operation);
1106 ret.ReturnCode = wrap(smartcard, SCardCancel, operation->hContext);
1107 scard_log_status_error_wlog(smartcard->log,
"SCardCancel", ret.ReturnCode);
1108 smartcard_trace_long_return_int(smartcard->log, &ret,
"Cancel");
1109 return ret.ReturnCode;
1112static LONG smartcard_ConnectA_Call(scard_call_context* smartcard,
wStream* out,
1116 SCARDHANDLE hCard = 0;
1120 WINPR_ASSERT(smartcard);
1122 WINPR_ASSERT(operation);
1124 call = &operation->call.connectA;
1126 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1127 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1129 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1132 ret.ReturnCode = wrap(smartcard, SCardConnectA, operation->hContext, (
char*)call->szReader,
1133 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1134 &ret.dwActiveProtocol);
1135 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1136 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1138 status = smartcard_pack_connect_return(out, &ret);
1139 if (status != SCARD_S_SUCCESS)
1142 status = ret.ReturnCode;
1148static LONG smartcard_ConnectW_Call(scard_call_context* smartcard,
wStream* out,
1152 SCARDHANDLE hCard = 0;
1156 WINPR_ASSERT(smartcard);
1158 WINPR_ASSERT(operation);
1160 call = &operation->call.connectW;
1162 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1163 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1165 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1168 ret.ReturnCode = wrap(smartcard, SCardConnectW, operation->hContext, (WCHAR*)call->szReader,
1169 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1170 &ret.dwActiveProtocol);
1171 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1172 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1174 status = smartcard_pack_connect_return(out, &ret);
1175 if (status != SCARD_S_SUCCESS)
1178 status = ret.ReturnCode;
1184static LONG smartcard_Reconnect_Call(scard_call_context* smartcard,
wStream* out,
1191 WINPR_ASSERT(smartcard);
1193 WINPR_ASSERT(operation);
1195 call = &operation->call.reconnect;
1197 wrap(smartcard, SCardReconnect, operation->hCard, call->dwShareMode,
1198 call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
1199 scard_log_status_error_wlog(smartcard->log,
"SCardReconnect", ret.ReturnCode);
1200 status = smartcard_pack_reconnect_return(out, &ret);
1201 if (status != SCARD_S_SUCCESS)
1204 return ret.ReturnCode;
1207static LONG smartcard_Disconnect_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1213 WINPR_ASSERT(smartcard);
1215 WINPR_ASSERT(operation);
1217 call = &operation->call.hCardAndDisposition;
1219 ret.ReturnCode = wrap(smartcard, SCardDisconnect, operation->hCard, call->dwDisposition);
1220 scard_log_status_error_wlog(smartcard->log,
"SCardDisconnect", ret.ReturnCode);
1221 smartcard_trace_long_return_int(smartcard->log, &ret,
"Disconnect");
1223 return ret.ReturnCode;
1226static LONG smartcard_BeginTransaction_Call(scard_call_context* smartcard,
1227 WINPR_ATTR_UNUSED
wStream* out,
1232 WINPR_ASSERT(smartcard);
1234 WINPR_ASSERT(operation);
1236 ret.ReturnCode = wrap(smartcard, SCardBeginTransaction, operation->hCard);
1237 scard_log_status_error_wlog(smartcard->log,
"SCardBeginTransaction", ret.ReturnCode);
1238 smartcard_trace_long_return_int(smartcard->log, &ret,
"BeginTransaction");
1239 return ret.ReturnCode;
1242static LONG smartcard_EndTransaction_Call(scard_call_context* smartcard,
1243 WINPR_ATTR_UNUSED
wStream* out,
1249 WINPR_ASSERT(smartcard);
1251 WINPR_ASSERT(operation);
1253 call = &operation->call.hCardAndDisposition;
1255 ret.ReturnCode = wrap(smartcard, SCardEndTransaction, operation->hCard, call->dwDisposition);
1256 scard_log_status_error_wlog(smartcard->log,
"SCardEndTransaction", ret.ReturnCode);
1257 smartcard_trace_long_return_int(smartcard->log, &ret,
"EndTransaction");
1258 return ret.ReturnCode;
1261static LONG smartcard_State_Call(scard_call_context* smartcard,
wStream* out,
1267 WINPR_ASSERT(smartcard);
1269 WINPR_ASSERT(operation);
1271 ret.cbAtrLen = SCARD_ATR_LENGTH;
1272 ret.ReturnCode = wrap(smartcard, SCardState, operation->hCard, &ret.dwState, &ret.dwProtocol,
1273 (BYTE*)&ret.rgAtr, &ret.cbAtrLen);
1275 scard_log_status_error_wlog(smartcard->log,
"SCardState", ret.ReturnCode);
1276 status = smartcard_pack_state_return(out, &ret);
1277 if (status != SCARD_S_SUCCESS)
1280 return ret.ReturnCode;
1283static LONG smartcard_StatusA_Call(scard_call_context* smartcard,
wStream* out,
1288 DWORD cchReaderLen = 0;
1290 LPSTR mszReaderNames =
nullptr;
1293 WINPR_ASSERT(smartcard);
1295 WINPR_ASSERT(operation);
1297 call = &operation->call.status;
1299 call->cbAtrLen = 32;
1300 cbAtrLen = call->cbAtrLen;
1302 if (call->fmszReaderNamesIsNULL)
1305 cchReaderLen = SCARD_AUTOALLOCATE;
1307 status = ret.ReturnCode =
1308 wrap(smartcard, SCardStatusA, operation->hCard,
1309 call->fmszReaderNamesIsNULL ?
nullptr : (LPSTR)&mszReaderNames, &cchReaderLen,
1310 &ret.dwState, &ret.dwProtocol, cbAtrLen ? (BYTE*)&ret.pbAtr : nullptr, &cbAtrLen);
1312 scard_log_status_error_wlog(smartcard->log,
"SCardStatusA", status);
1313 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchReaderLen == SCARD_AUTOALLOCATE))
1314 return SCARD_F_UNKNOWN_ERROR;
1316 if (status == SCARD_S_SUCCESS)
1318 if (!call->fmszReaderNamesIsNULL)
1319 ret.mszReaderNames = (BYTE*)mszReaderNames;
1321 ret.cBytes = cchReaderLen;
1324 ret.cbAtrLen = cbAtrLen;
1327 status = smartcard_pack_status_return(out, &ret, FALSE);
1330 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1332 if (status != SCARD_S_SUCCESS)
1334 return ret.ReturnCode;
1337static LONG smartcard_StatusW_Call(scard_call_context* smartcard,
wStream* out,
1342 LPWSTR mszReaderNames =
nullptr;
1346 WINPR_ASSERT(smartcard);
1348 WINPR_ASSERT(operation);
1350 call = &operation->call.status;
1356 cbAtrLen = call->cbAtrLen = 32;
1358 if (call->fmszReaderNamesIsNULL)
1361 ret.cBytes = SCARD_AUTOALLOCATE;
1363 status = ret.ReturnCode =
1364 wrap(smartcard, SCardStatusW, operation->hCard,
1365 call->fmszReaderNamesIsNULL ?
nullptr : (LPWSTR)&mszReaderNames, &ret.cBytes,
1366 &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
1367 scard_log_status_error_wlog(smartcard->log,
"SCardStatusW", status);
1368 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cBytes == SCARD_AUTOALLOCATE))
1369 return SCARD_F_UNKNOWN_ERROR;
1372 if (status == SCARD_S_SUCCESS)
1374 if (!call->fmszReaderNamesIsNULL)
1375 ret.mszReaderNames = (BYTE*)mszReaderNames;
1377 ret.cbAtrLen = cbAtrLen;
1380 if (ret.cBytes != SCARD_AUTOALLOCATE)
1383 WINPR_ASSERT(ret.cBytes < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
1384 blen =
sizeof(WCHAR) * ret.cBytes;
1385 WINPR_ASSERT(blen <= UINT32_MAX);
1386 ret.cBytes = (UINT32)blen;
1389 status = smartcard_pack_status_return(out, &ret, TRUE);
1390 if (status != SCARD_S_SUCCESS)
1394 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1396 return ret.ReturnCode;
1399static LONG smartcard_Transmit_Call(scard_call_context* smartcard,
wStream* out,
1406 WINPR_ASSERT(smartcard);
1408 WINPR_ASSERT(operation);
1410 call = &operation->call.transmit;
1411 ret.cbRecvLength = 0;
1412 ret.pbRecvBuffer =
nullptr;
1414 if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
1416 if (call->cbRecvLength >= 66560)
1417 call->cbRecvLength = 66560;
1419 const UINT32 cbRecvLength = call->cbRecvLength;
1420 ret.pbRecvBuffer = (BYTE*)malloc(cbRecvLength);
1422 if (!ret.pbRecvBuffer)
1423 return STATUS_NO_MEMORY;
1424 ret.cbRecvLength = cbRecvLength;
1427 ret.pioRecvPci = call->pioRecvPci;
1429 wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
1430 call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
1432 scard_log_status_error_wlog(smartcard->log,
"SCardTransmit", ret.ReturnCode);
1434 status = smartcard_pack_transmit_return(out, &ret);
1435 free(ret.pbRecvBuffer);
1437 if (status != SCARD_S_SUCCESS)
1439 return ret.ReturnCode;
1442static LONG smartcard_Control_Call(scard_call_context* smartcard,
wStream* out,
1449 WINPR_ASSERT(smartcard);
1451 WINPR_ASSERT(operation);
1453 call = &operation->call.control;
1454 ret.pvOutBuffer = (BYTE*)malloc(call->cbOutBufferSize);
1456 if (!ret.pvOutBuffer)
1457 return SCARD_E_NO_MEMORY;
1458 ret.cbOutBufferSize = call->cbOutBufferSize;
1461 wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
1462 call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
1463 scard_log_status_error_wlog(smartcard->log,
"SCardControl", ret.ReturnCode);
1464 status = smartcard_pack_control_return(out, &ret);
1466 free(ret.pvOutBuffer);
1467 if (status != SCARD_S_SUCCESS)
1469 return ret.ReturnCode;
1472static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard,
wStream* out,
1475 BOOL autoAllocate = FALSE;
1477 DWORD cbAttrLen = 0;
1478 LPBYTE pbAttr =
nullptr;
1482 WINPR_ASSERT(smartcard);
1483 WINPR_ASSERT(operation);
1485 call = &operation->call.getAttrib;
1487 if (!call->fpbAttrIsNULL)
1489 autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE);
1490 cbAttrLen = call->cbAttrLen;
1491 if (cbAttrLen && !autoAllocate)
1493 ret.pbAttr = (BYTE*)malloc(cbAttrLen);
1496 return SCARD_E_NO_MEMORY;
1499 pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
1503 wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
1504 scard_log_status_error_wlog(smartcard->log,
"SCardGetAttrib", ret.ReturnCode);
1505 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cbAttrLen == SCARD_AUTOALLOCATE))
1506 return SCARD_F_UNKNOWN_ERROR;
1508 ret.cbAttrLen = cbAttrLen;
1510 status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
1513 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
1519static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1525 WINPR_ASSERT(smartcard);
1527 WINPR_ASSERT(operation);
1529 call = &operation->call.setAttrib;
1531 ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
1533 scard_log_status_error_wlog(smartcard->log,
"SCardSetAttrib", ret.ReturnCode);
1534 smartcard_trace_long_return_int(smartcard->log, &ret,
"SetAttrib");
1536 return ret.ReturnCode;
1539static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard,
1540 WINPR_ATTR_UNUSED
wStream* out,
1543 LONG status = SCARD_S_SUCCESS;
1545 WINPR_ASSERT(smartcard);
1547 WINPR_UNUSED(operation);
1549 if (!smartcard->StartedEvent)
1550 smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
1552 if (!smartcard->StartedEvent)
1553 status = SCARD_E_NO_SERVICE;
1558static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard,
wStream* out,
1566 WINPR_ASSERT(smartcard);
1567 WINPR_ASSERT(operation);
1569 call = &operation->call.locateCardsByATRA;
1573 return STATUS_NO_MEMORY;
1575 for (UINT32 i = 0; i < call->cReaders; i++)
1578 state->szReader = call->rgReaderStates[i].szReader;
1579 state->dwCurrentState = call->rgReaderStates[i].dwCurrentState;
1580 state->dwEventState = call->rgReaderStates[i].dwEventState;
1581 state->cbAtr = call->rgReaderStates[i].cbAtr;
1582 CopyMemory(&(state->rgbAtr), &(call->rgReaderStates[i].rgbAtr), 36);
1585 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1586 0x000001F4, states, call->cReaders);
1588 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", status);
1589 for (UINT32 i = 0; i < call->cAtrs; i++)
1591 for (UINT32 j = 0; j < call->cReaders; j++)
1593 for (UINT32 k = 0; k < call->rgAtrMasks[i].cbAtr; k++)
1595 if ((call->rgAtrMasks[i].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]) !=
1596 (states[j].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]))
1601 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1606 ret.rgReaderStates =
nullptr;
1608 if (call->cReaders > 0)
1609 ret.rgReaderStates =
1612 if (!ret.rgReaderStates)
1615 return STATUS_NO_MEMORY;
1618 ret.cReaders = call->cReaders;
1620 for (UINT32 i = 0; i < ret.cReaders; i++)
1623 ret.rgReaderStates[i].dwCurrentState = state->dwCurrentState;
1624 ret.rgReaderStates[i].dwEventState = state->dwEventState;
1625 ret.rgReaderStates[i].cbAtr = state->cbAtr;
1626 CopyMemory(&(ret.rgReaderStates[i].rgbAtr), &(state->rgbAtr),
1627 sizeof(ret.rgReaderStates[i].rgbAtr));
1632 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1634 free(ret.rgReaderStates);
1635 if (status != SCARD_S_SUCCESS)
1637 return ret.ReturnCode;
1640LONG smartcard_irp_device_control_call(scard_call_context* ctx,
wStream* out, NTSTATUS* pIoStatus,
1645 size_t objectBufferLength = 0;
1649 WINPR_ASSERT(pIoStatus);
1650 WINPR_ASSERT(operation);
1652 const UINT32 ioControlCode = operation->ioControlCode;
1660 const size_t outMaxLen = MAX(2048, operation->outputBufferLength);
1661 if (!Stream_EnsureRemainingCapacity(out, outMaxLen))
1662 return SCARD_E_NO_MEMORY;
1665 Stream_Write_UINT32(out, 0);
1666 Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH);
1667 Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH);
1668 Stream_Write_UINT32(out, 0);
1671 switch (ioControlCode)
1673 case SCARD_IOCTL_ESTABLISHCONTEXT:
1674 result = smartcard_EstablishContext_Call(ctx, out, operation);
1677 case SCARD_IOCTL_RELEASECONTEXT:
1678 result = smartcard_ReleaseContext_Call(ctx, out, operation);
1681 case SCARD_IOCTL_ISVALIDCONTEXT:
1682 result = smartcard_IsValidContext_Call(ctx, out, operation);
1685 case SCARD_IOCTL_LISTREADERGROUPSA:
1686 result = smartcard_ListReaderGroupsA_Call(ctx, out, operation);
1689 case SCARD_IOCTL_LISTREADERGROUPSW:
1690 result = smartcard_ListReaderGroupsW_Call(ctx, out, operation);
1693 case SCARD_IOCTL_LISTREADERSA:
1694 result = smartcard_ListReadersA_Call(ctx, out, operation);
1697 case SCARD_IOCTL_LISTREADERSW:
1698 result = smartcard_ListReadersW_Call(ctx, out, operation);
1701 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1702 result = smartcard_IntroduceReaderGroupA_Call(ctx, out, operation);
1705 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1706 result = smartcard_IntroduceReaderGroupW_Call(ctx, out, operation);
1709 case SCARD_IOCTL_FORGETREADERGROUPA:
1710 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
1713 case SCARD_IOCTL_FORGETREADERGROUPW:
1714 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
1717 case SCARD_IOCTL_INTRODUCEREADERA:
1718 result = smartcard_IntroduceReaderA_Call(ctx, out, operation);
1721 case SCARD_IOCTL_INTRODUCEREADERW:
1722 result = smartcard_IntroduceReaderW_Call(ctx, out, operation);
1725 case SCARD_IOCTL_FORGETREADERA:
1726 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
1729 case SCARD_IOCTL_FORGETREADERW:
1730 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
1733 case SCARD_IOCTL_ADDREADERTOGROUPA:
1734 result = smartcard_AddReaderToGroupA_Call(ctx, out, operation);
1737 case SCARD_IOCTL_ADDREADERTOGROUPW:
1738 result = smartcard_AddReaderToGroupW_Call(ctx, out, operation);
1741 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1742 result = smartcard_RemoveReaderFromGroupA_Call(ctx, out, operation);
1745 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1746 result = smartcard_RemoveReaderFromGroupW_Call(ctx, out, operation);
1749 case SCARD_IOCTL_LOCATECARDSA:
1750 result = smartcard_LocateCardsA_Call(ctx, out, operation);
1753 case SCARD_IOCTL_LOCATECARDSW:
1754 result = smartcard_LocateCardsW_Call(ctx, out, operation);
1757 case SCARD_IOCTL_GETSTATUSCHANGEA:
1758 result = smartcard_GetStatusChangeA_Call(ctx, out, operation);
1761 case SCARD_IOCTL_GETSTATUSCHANGEW:
1762 result = smartcard_GetStatusChangeW_Call(ctx, out, operation);
1765 case SCARD_IOCTL_CANCEL:
1766 result = smartcard_Cancel_Call(ctx, out, operation);
1769 case SCARD_IOCTL_CONNECTA:
1770 result = smartcard_ConnectA_Call(ctx, out, operation);
1773 case SCARD_IOCTL_CONNECTW:
1774 result = smartcard_ConnectW_Call(ctx, out, operation);
1777 case SCARD_IOCTL_RECONNECT:
1778 result = smartcard_Reconnect_Call(ctx, out, operation);
1781 case SCARD_IOCTL_DISCONNECT:
1782 result = smartcard_Disconnect_Call(ctx, out, operation);
1785 case SCARD_IOCTL_BEGINTRANSACTION:
1786 result = smartcard_BeginTransaction_Call(ctx, out, operation);
1789 case SCARD_IOCTL_ENDTRANSACTION:
1790 result = smartcard_EndTransaction_Call(ctx, out, operation);
1793 case SCARD_IOCTL_STATE:
1794 result = smartcard_State_Call(ctx, out, operation);
1797 case SCARD_IOCTL_STATUSA:
1798 result = smartcard_StatusA_Call(ctx, out, operation);
1801 case SCARD_IOCTL_STATUSW:
1802 result = smartcard_StatusW_Call(ctx, out, operation);
1805 case SCARD_IOCTL_TRANSMIT:
1806 result = smartcard_Transmit_Call(ctx, out, operation);
1809 case SCARD_IOCTL_CONTROL:
1810 result = smartcard_Control_Call(ctx, out, operation);
1813 case SCARD_IOCTL_GETATTRIB:
1814 result = smartcard_GetAttrib_Call(ctx, out, operation);
1817 case SCARD_IOCTL_SETATTRIB:
1818 result = smartcard_SetAttrib_Call(ctx, out, operation);
1821 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
1822 result = smartcard_AccessStartedEvent_Call(ctx, out, operation);
1825 case SCARD_IOCTL_LOCATECARDSBYATRA:
1826 result = smartcard_LocateCardsByATRA_Call(ctx, out, operation);
1829 case SCARD_IOCTL_LOCATECARDSBYATRW:
1830 result = smartcard_LocateCardsW_Call(ctx, out, operation);
1833 case SCARD_IOCTL_READCACHEA:
1834 result = smartcard_ReadCacheA_Call(ctx, out, operation);
1837 case SCARD_IOCTL_READCACHEW:
1838 result = smartcard_ReadCacheW_Call(ctx, out, operation);
1841 case SCARD_IOCTL_WRITECACHEA:
1842 result = smartcard_WriteCacheA_Call(ctx, out, operation);
1845 case SCARD_IOCTL_WRITECACHEW:
1846 result = smartcard_WriteCacheW_Call(ctx, out, operation);
1849 case SCARD_IOCTL_GETTRANSMITCOUNT:
1850 result = smartcard_GetTransmitCount_Call(ctx, out, operation);
1853 case SCARD_IOCTL_RELEASETARTEDEVENT:
1854 result = smartcard_ReleaseStartedEvent_Call(ctx, out, operation);
1857 case SCARD_IOCTL_GETREADERICON:
1858 result = smartcard_GetReaderIcon_Call(ctx, out, operation);
1861 case SCARD_IOCTL_GETDEVICETYPEID:
1862 result = smartcard_GetDeviceTypeId_Call(ctx, out, operation);
1866 result = STATUS_UNSUCCESSFUL;
1876 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
1877 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
1879 offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
1880 const LONG rc = smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
1881 if (rc != SCARD_S_SUCCESS)
1885 if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
1886 (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
1887 (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
1889 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
1890 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
1893 *pIoStatus = STATUS_SUCCESS;
1895 if ((result & 0xC0000000L) == 0xC0000000L)
1898 *pIoStatus = result;
1900 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
1901 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
1904 Stream_SealLength(out);
1905 size_t outputBufferLength = Stream_Length(out);
1906 size_t dataEndPos = outputBufferLength;
1908 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1909 outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1910 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1911 objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
1912 WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
1913 WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
1914 if (!Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH))
1915 return SCARD_E_BAD_SEEK;
1924 if (outputBufferLength > operation->outputBufferLength)
1926 WLog_Print(ctx->log, WLOG_DEBUG,
1927 "IRP warn: expected outputBufferLength %" PRIuz
", but current limit %" PRIu32
1928 ", respond with STATUS_BUFFER_TOO_SMALL for retransmit with larger buffer",
1929 outputBufferLength, operation->outputBufferLength);
1931 *pIoStatus = STATUS_BUFFER_TOO_SMALL;
1932 result = *pIoStatus;
1933 outputBufferLength = 0;
1934 objectBufferLength = 0;
1938 WLog_Print(ctx->log, WLOG_TRACE,
"IRP trace: outputBufferLength %" PRIuz
", limit %" PRIu32,
1939 outputBufferLength, operation->outputBufferLength);
1943 Stream_Write_UINT32(out, (UINT32)outputBufferLength);
1944 smartcard_pack_common_type_header(out);
1945 smartcard_pack_private_type_header(
1946 out, (UINT32)objectBufferLength);
1947 Stream_Write_INT32(out, result);
1948 if (result == STATUS_BUFFER_TOO_SMALL)
1949 Stream_SealLength(out);
1950 else if (!Stream_SetPosition(out, dataEndPos))
1951 return SCARD_E_BAD_SEEK;
1952 return SCARD_S_SUCCESS;
1955void context_free(
void* arg)
1957 struct s_scard_context_element* element = arg;
1961 if (element->fn_free)
1962 element->fn_free(element->context);
1966#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
1967scard_call_context* smartcard_call_context_new(
const rdpSettings* settings)
1970 if (!inst || !inst->context)
1972 return smartcard_call_context_new_with_context(inst->context);
1976scard_call_context* smartcard_call_context_new_with_context(rdpContext* context)
1978 WINPR_ASSERT(context);
1979 scard_call_context* ctx = calloc(1,
sizeof(scard_call_context));
1983 ctx->context = context;
1985 const rdpSettings* settings = context->settings;
1986 WINPR_ASSERT(settings);
1988 ctx->log = WLog_Get(SCARD_TAG);
1989 WINPR_ASSERT(ctx->log);
1991 ctx->stopEvent = CreateEventA(
nullptr, TRUE, FALSE,
nullptr);
1992 if (!ctx->stopEvent)
1995 ctx->names = LinkedList_New();
1999#if defined(WITH_SMARTCARD_EMULATE)
2003 if (ctx->useEmulatedCard)
2005#if defined(WITH_SMARTCARD_EMULATE)
2006 ctx->emulation = Emulate_New(settings);
2007 if (!ctx->emulation)
2010 WLog_Print(ctx->log, WLOG_ERROR,
"Smartcard emulation requested, but not supported!");
2019 ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
2021 if (!ctx->hWinSCardLibrary)
2023 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard library: '%s'",
2028 if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
2030 ctx->pWinSCardApi = &ctx->WinSCardApi;
2034 ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
2037 if (!ctx->pWinSCardApi)
2039 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard API!");
2044 ctx->rgSCardContextList = HashTable_New(FALSE);
2045 if (!ctx->rgSCardContextList)
2049 wObject* obj = HashTable_ValueObject(ctx->rgSCardContextList);
2056 WINPR_PRAGMA_DIAG_PUSH
2057 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2058 smartcard_call_context_free(ctx);
2059 WINPR_PRAGMA_DIAG_POP
2063void smartcard_call_context_free(scard_call_context* ctx)
2068 smartcard_call_context_signal_stop(ctx, FALSE);
2070 LinkedList_Free(ctx->names);
2071 if (ctx->StartedEvent)
2073 WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
2074 wrap_raw(ctx, SCardReleaseStartedEvent);
2077 if (ctx->useEmulatedCard)
2079#ifdef WITH_SMARTCARD_EMULATE
2082 Emulate_Free(ctx->emulation);
2083 ctx->emulation =
nullptr;
2088 if (ctx->hWinSCardLibrary)
2091 FreeLibrary(ctx->hWinSCardLibrary);
2092 ctx->hWinSCardLibrary =
nullptr;
2095 ctx->pWinSCardApi =
nullptr;
2097 HashTable_Free(ctx->rgSCardContextList);
2098 (void)CloseHandle(ctx->stopEvent);
2102BOOL smartcard_call_context_add(scard_call_context* ctx,
const char* name)
2106 return LinkedList_AddLast(ctx->names, name);
2109BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2112 if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
2114 wrap(ctx, SCardCancel, hContext);
2119BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2122 wrap(ctx, SCardReleaseContext, hContext);
2126BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
2131 HashTable_Clear(ctx->rgSCardContextList);
2135BOOL smarcard_call_set_callbacks(scard_call_context* ctx,
void* userdata,
2136 void* (*fn_new)(
void*, SCARDCONTEXT),
void (*fn_free)(
void*))
2139 ctx->userdata = userdata;
2140 ctx->fn_new = fn_new;
2141 ctx->fn_free = fn_free;
2145void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2147 struct s_scard_context_element* element =
nullptr;
2150 element = HashTable_GetItemValue(ctx->rgSCardContextList, (
void*)hContext);
2153 return element->context;
2156BOOL smartcard_call_is_configured(scard_call_context* ctx)
2160#if defined(WITH_SMARTCARD_EMULATE)
2161 if (ctx->useEmulatedCard)
2162 return Emulate_IsConfigured(ctx->emulation);
2168BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
2172 if (!ctx->stopEvent)
2176 return ResetEvent(ctx->stopEvent);
2178 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