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.cReaders = call->cReaders;
654 ret.rgReaderStates =
nullptr;
656 if (ret.cReaders > 0)
660 if (!ret.rgReaderStates)
661 return STATUS_NO_MEMORY;
664 for (UINT32 x = 0; x < ret.cReaders; x++)
666 ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
667 ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
668 ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
669 CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
670 sizeof(ret.rgReaderStates[x].rgbAtr));
673 status = smartcard_pack_locate_cards_return(out, &ret);
675 if (status != SCARD_S_SUCCESS)
678 return ret.ReturnCode;
681static LONG smartcard_LocateCardsW_Call(scard_call_context* smartcard,
wStream* out,
688 WINPR_ASSERT(smartcard);
689 WINPR_ASSERT(operation);
691 call = &operation->call.locateCardsW;
693 ret.ReturnCode = wrap(smartcard, SCardLocateCardsW, operation->hContext, call->mszCards,
694 call->rgReaderStates, call->cReaders);
695 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsW", ret.ReturnCode);
696 ret.cReaders = call->cReaders;
697 ret.rgReaderStates =
nullptr;
699 if (ret.cReaders > 0)
703 if (!ret.rgReaderStates)
704 return STATUS_NO_MEMORY;
707 for (UINT32 x = 0; x < ret.cReaders; x++)
709 ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
710 ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
711 ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
712 CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
713 sizeof(ret.rgReaderStates[x].rgbAtr));
716 status = smartcard_pack_locate_cards_return(out, &ret);
718 if (status != SCARD_S_SUCCESS)
721 return ret.ReturnCode;
724static LONG smartcard_ReadCacheA_Call(scard_call_context* smartcard,
wStream* out,
732 WINPR_ASSERT(smartcard);
734 WINPR_ASSERT(operation);
736 call = &operation->call.readCacheA;
737 autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE);
739 if (!call->Common.fPbDataIsNULL)
741 ret.cbDataLen = call->Common.cbDataLen;
744 ret.pbData = malloc(ret.cbDataLen);
746 return SCARD_F_INTERNAL_ERROR;
751 ret.ReturnCode = wrap(smartcard, SCardReadCacheA, operation->hContext,
752 call->Common.CardIdentifier, call->Common.FreshnessCounter,
753 call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
756 wrap(smartcard, SCardReadCacheA, operation->hContext, call->Common.CardIdentifier,
757 call->Common.FreshnessCounter, call->szLookupName, ret.pbData, &ret.cbDataLen);
759 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, call->szLookupName,
762 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
763 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
765 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheA", ret.ReturnCode);
768 status = smartcard_pack_read_cache_return(out, &ret);
770 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
773 if (status != SCARD_S_SUCCESS)
776 return ret.ReturnCode;
779static LONG smartcard_ReadCacheW_Call(scard_call_context* smartcard,
wStream* out,
786 WINPR_ASSERT(smartcard);
788 WINPR_ASSERT(operation);
790 call = &operation->call.readCacheW;
792 if (!call->Common.fPbDataIsNULL)
793 ret.cbDataLen = SCARD_AUTOALLOCATE;
796 wrap(smartcard, SCardReadCacheW, operation->hContext, call->Common.CardIdentifier,
797 call->Common.FreshnessCounter, call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
799 if (WLog_IsLevelActive(smartcard->log, WLOG_TRACE))
801 char buffer[128] = WINPR_C_ARRAY_INIT;
802 (void)ConvertWCharToUtf8(call->szLookupName, buffer,
sizeof(buffer));
803 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, buffer, ret.cbDataLen);
805 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
806 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
808 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheW", ret.ReturnCode);
811 status = smartcard_pack_read_cache_return(out, &ret);
813 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
815 if (status != SCARD_S_SUCCESS)
818 return ret.ReturnCode;
821static LONG smartcard_WriteCacheA_Call(scard_call_context* smartcard,
822 WINPR_ATTR_UNUSED
wStream* out,
828 WINPR_ASSERT(smartcard);
830 WINPR_ASSERT(operation);
832 call = &operation->call.writeCacheA;
834 ret.ReturnCode = wrap(smartcard, SCardWriteCacheA, operation->hContext,
835 call->Common.CardIdentifier, call->Common.FreshnessCounter,
836 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
837 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheA", ret.ReturnCode);
838 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheA");
839 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, call->szLookupName,
840 call->Common.cbDataLen);
841 return ret.ReturnCode;
844static LONG smartcard_WriteCacheW_Call(scard_call_context* smartcard,
845 WINPR_ATTR_UNUSED
wStream* out,
851 WINPR_ASSERT(smartcard);
853 WINPR_ASSERT(operation);
855 call = &operation->call.writeCacheW;
857 ret.ReturnCode = wrap(smartcard, SCardWriteCacheW, operation->hContext,
858 call->Common.CardIdentifier, call->Common.FreshnessCounter,
859 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
860 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheW", ret.ReturnCode);
861 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheW");
863 if (WLog_IsLevelActive(smartcard->log, WLOG_TRACE))
865 char buffer[128] = WINPR_C_ARRAY_INIT;
866 (void)ConvertWCharToUtf8(call->szLookupName, buffer,
sizeof(buffer));
867 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, buffer,
868 call->Common.cbDataLen);
870 return ret.ReturnCode;
873static LONG smartcard_GetTransmitCount_Call(scard_call_context* smartcard,
wStream* out,
879 WINPR_ASSERT(smartcard);
881 WINPR_ASSERT(operation);
883 ret.ReturnCode = wrap(smartcard, SCardGetTransmitCount, operation->hCard, &ret.cTransmitCount);
884 scard_log_status_error_wlog(smartcard->log,
"SCardGetTransmitCount", ret.ReturnCode);
885 status = smartcard_pack_get_transmit_count_return(out, &ret);
886 if (status != SCARD_S_SUCCESS)
889 return ret.ReturnCode;
892static LONG smartcard_ReleaseStartedEvent_Call(scard_call_context* smartcard,
wStream* out,
895 WINPR_UNUSED(smartcard);
897 WINPR_UNUSED(operation);
899 WLog_Print(smartcard->log, WLOG_WARN,
900 "According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
901 "this is not supported?!?");
902 return SCARD_E_UNSUPPORTED_FEATURE;
905static LONG smartcard_GetReaderIcon_Call(scard_call_context* smartcard,
wStream* out,
912 WINPR_ASSERT(smartcard);
914 WINPR_ASSERT(operation);
916 call = &operation->call.getReaderIcon;
918 ret.cbDataLen = SCARD_AUTOALLOCATE;
919 ret.ReturnCode = wrap(smartcard, SCardGetReaderIconW, operation->hContext, call->szReaderName,
920 (LPBYTE)&ret.pbData, &ret.cbDataLen);
921 scard_log_status_error_wlog(smartcard->log,
"SCardGetReaderIconW", ret.ReturnCode);
922 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cbDataLen == SCARD_AUTOALLOCATE))
923 return SCARD_F_UNKNOWN_ERROR;
925 status = smartcard_pack_get_reader_icon_return(out, &ret);
926 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
927 if (status != SCARD_S_SUCCESS)
930 return ret.ReturnCode;
933static LONG smartcard_GetDeviceTypeId_Call(scard_call_context* smartcard,
wStream* out,
940 WINPR_ASSERT(smartcard);
942 WINPR_ASSERT(operation);
944 call = &operation->call.getDeviceTypeId;
946 ret.ReturnCode = wrap(smartcard, SCardGetDeviceTypeIdW, operation->hContext, call->szReaderName,
948 scard_log_status_error_wlog(smartcard->log,
"SCardGetDeviceTypeIdW", ret.ReturnCode);
950 status = smartcard_pack_device_type_id_return(out, &ret);
951 if (status != SCARD_S_SUCCESS)
954 return ret.ReturnCode;
957static BOOL smartcard_context_was_aborted(scard_call_context* smartcard)
959 WINPR_ASSERT(smartcard);
961 HANDLE handles[] = { smartcard->stopEvent, freerdp_abort_event(smartcard->context) };
962 const DWORD rc = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, 0);
963 return (rc >= WAIT_OBJECT_0) && (rc <= WAIT_OBJECT_0 + ARRAYSIZE(handles));
966static LONG smartcard_GetStatusChangeA_Call(scard_call_context* smartcard,
wStream* out,
969 LONG status = STATUS_NO_MEMORY;
971 const DWORD dwTimeStep = 100;
976 WINPR_ASSERT(smartcard);
978 WINPR_ASSERT(operation);
980 call = &operation->call.getStatusChangeA;
981 dwTimeOut = call->dwTimeOut;
983 if (call->cReaders > 0)
985 ret.cReaders = call->cReaders;
988 if (!rgReaderStates || !ret.rgReaderStates)
992 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
994 if (call->cReaders > 0)
995 memcpy(rgReaderStates, call->rgReaderStates,
997 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
998 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
999 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1001 if (smartcard_context_was_aborted(smartcard))
1003 if (dwTimeOut != INFINITE)
1006 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", ret.ReturnCode);
1008 for (UINT32 index = 0; index < ret.cReaders; index++)
1013 rout->dwCurrentState = cur->dwCurrentState;
1014 rout->dwEventState = cur->dwEventState;
1015 rout->cbAtr = cur->cbAtr;
1016 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1019 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1021 free(ret.rgReaderStates);
1022 free(rgReaderStates);
1023 if (status != SCARD_S_SUCCESS)
1025 return ret.ReturnCode;
1028static LONG smartcard_GetStatusChangeW_Call(scard_call_context* smartcard,
wStream* out,
1031 LONG status = STATUS_NO_MEMORY;
1032 DWORD dwTimeOut = 0;
1033 const DWORD dwTimeStep = 100;
1037 WINPR_ASSERT(smartcard);
1039 WINPR_ASSERT(operation);
1042 dwTimeOut = call->dwTimeOut;
1044 if (call->cReaders > 0)
1046 ret.cReaders = call->cReaders;
1049 if (!rgReaderStates || !ret.rgReaderStates)
1053 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
1055 if (call->cReaders > 0)
1056 memcpy(rgReaderStates, call->rgReaderStates,
1059 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
1060 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
1062 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1064 if (smartcard_context_was_aborted(smartcard))
1066 if (dwTimeOut != INFINITE)
1069 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeW", ret.ReturnCode);
1071 for (UINT32 index = 0; index < ret.cReaders; index++)
1076 rout->dwCurrentState = cur->dwCurrentState;
1077 rout->dwEventState = cur->dwEventState;
1078 rout->cbAtr = cur->cbAtr;
1079 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1082 status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
1084 free(ret.rgReaderStates);
1085 free(rgReaderStates);
1086 if (status != SCARD_S_SUCCESS)
1088 return ret.ReturnCode;
1091static LONG smartcard_Cancel_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1096 WINPR_ASSERT(smartcard);
1098 WINPR_ASSERT(operation);
1100 ret.ReturnCode = wrap(smartcard, SCardCancel, operation->hContext);
1101 scard_log_status_error_wlog(smartcard->log,
"SCardCancel", ret.ReturnCode);
1102 smartcard_trace_long_return_int(smartcard->log, &ret,
"Cancel");
1103 return ret.ReturnCode;
1106static LONG smartcard_ConnectA_Call(scard_call_context* smartcard,
wStream* out,
1110 SCARDHANDLE hCard = 0;
1114 WINPR_ASSERT(smartcard);
1116 WINPR_ASSERT(operation);
1118 call = &operation->call.connectA;
1120 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1121 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1123 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1126 ret.ReturnCode = wrap(smartcard, SCardConnectA, operation->hContext, (
char*)call->szReader,
1127 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1128 &ret.dwActiveProtocol);
1129 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1130 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1132 status = smartcard_pack_connect_return(out, &ret);
1133 if (status != SCARD_S_SUCCESS)
1136 status = ret.ReturnCode;
1142static LONG smartcard_ConnectW_Call(scard_call_context* smartcard,
wStream* out,
1146 SCARDHANDLE hCard = 0;
1150 WINPR_ASSERT(smartcard);
1152 WINPR_ASSERT(operation);
1154 call = &operation->call.connectW;
1156 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1157 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1159 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1162 ret.ReturnCode = wrap(smartcard, SCardConnectW, operation->hContext, (WCHAR*)call->szReader,
1163 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1164 &ret.dwActiveProtocol);
1165 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1166 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1168 status = smartcard_pack_connect_return(out, &ret);
1169 if (status != SCARD_S_SUCCESS)
1172 status = ret.ReturnCode;
1178static LONG smartcard_Reconnect_Call(scard_call_context* smartcard,
wStream* out,
1185 WINPR_ASSERT(smartcard);
1187 WINPR_ASSERT(operation);
1189 call = &operation->call.reconnect;
1191 wrap(smartcard, SCardReconnect, operation->hCard, call->dwShareMode,
1192 call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
1193 scard_log_status_error_wlog(smartcard->log,
"SCardReconnect", ret.ReturnCode);
1194 status = smartcard_pack_reconnect_return(out, &ret);
1195 if (status != SCARD_S_SUCCESS)
1198 return ret.ReturnCode;
1201static LONG smartcard_Disconnect_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1207 WINPR_ASSERT(smartcard);
1209 WINPR_ASSERT(operation);
1211 call = &operation->call.hCardAndDisposition;
1213 ret.ReturnCode = wrap(smartcard, SCardDisconnect, operation->hCard, call->dwDisposition);
1214 scard_log_status_error_wlog(smartcard->log,
"SCardDisconnect", ret.ReturnCode);
1215 smartcard_trace_long_return_int(smartcard->log, &ret,
"Disconnect");
1217 return ret.ReturnCode;
1220static LONG smartcard_BeginTransaction_Call(scard_call_context* smartcard,
1221 WINPR_ATTR_UNUSED
wStream* out,
1226 WINPR_ASSERT(smartcard);
1228 WINPR_ASSERT(operation);
1230 ret.ReturnCode = wrap(smartcard, SCardBeginTransaction, operation->hCard);
1231 scard_log_status_error_wlog(smartcard->log,
"SCardBeginTransaction", ret.ReturnCode);
1232 smartcard_trace_long_return_int(smartcard->log, &ret,
"BeginTransaction");
1233 return ret.ReturnCode;
1236static LONG smartcard_EndTransaction_Call(scard_call_context* smartcard,
1237 WINPR_ATTR_UNUSED
wStream* out,
1243 WINPR_ASSERT(smartcard);
1245 WINPR_ASSERT(operation);
1247 call = &operation->call.hCardAndDisposition;
1249 ret.ReturnCode = wrap(smartcard, SCardEndTransaction, operation->hCard, call->dwDisposition);
1250 scard_log_status_error_wlog(smartcard->log,
"SCardEndTransaction", ret.ReturnCode);
1251 smartcard_trace_long_return_int(smartcard->log, &ret,
"EndTransaction");
1252 return ret.ReturnCode;
1255static LONG smartcard_State_Call(scard_call_context* smartcard,
wStream* out,
1261 WINPR_ASSERT(smartcard);
1263 WINPR_ASSERT(operation);
1265 ret.cbAtrLen = SCARD_ATR_LENGTH;
1266 ret.ReturnCode = wrap(smartcard, SCardState, operation->hCard, &ret.dwState, &ret.dwProtocol,
1267 (BYTE*)&ret.rgAtr, &ret.cbAtrLen);
1269 scard_log_status_error_wlog(smartcard->log,
"SCardState", ret.ReturnCode);
1270 status = smartcard_pack_state_return(out, &ret);
1271 if (status != SCARD_S_SUCCESS)
1274 return ret.ReturnCode;
1277static LONG smartcard_StatusA_Call(scard_call_context* smartcard,
wStream* out,
1282 DWORD cchReaderLen = 0;
1284 LPSTR mszReaderNames =
nullptr;
1287 WINPR_ASSERT(smartcard);
1289 WINPR_ASSERT(operation);
1291 call = &operation->call.status;
1293 call->cbAtrLen = 32;
1294 cbAtrLen = call->cbAtrLen;
1296 if (call->fmszReaderNamesIsNULL)
1299 cchReaderLen = SCARD_AUTOALLOCATE;
1301 status = ret.ReturnCode =
1302 wrap(smartcard, SCardStatusA, operation->hCard,
1303 call->fmszReaderNamesIsNULL ?
nullptr : (LPSTR)&mszReaderNames, &cchReaderLen,
1304 &ret.dwState, &ret.dwProtocol, cbAtrLen ? (BYTE*)&ret.pbAtr : nullptr, &cbAtrLen);
1306 scard_log_status_error_wlog(smartcard->log,
"SCardStatusA", status);
1307 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchReaderLen == SCARD_AUTOALLOCATE))
1308 return SCARD_F_UNKNOWN_ERROR;
1310 if (status == SCARD_S_SUCCESS)
1312 if (!call->fmszReaderNamesIsNULL)
1313 ret.mszReaderNames = (BYTE*)mszReaderNames;
1315 ret.cBytes = cchReaderLen;
1318 ret.cbAtrLen = cbAtrLen;
1321 status = smartcard_pack_status_return(out, &ret, FALSE);
1324 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1326 if (status != SCARD_S_SUCCESS)
1328 return ret.ReturnCode;
1331static LONG smartcard_StatusW_Call(scard_call_context* smartcard,
wStream* out,
1336 LPWSTR mszReaderNames =
nullptr;
1340 WINPR_ASSERT(smartcard);
1342 WINPR_ASSERT(operation);
1344 call = &operation->call.status;
1350 cbAtrLen = call->cbAtrLen = 32;
1352 if (call->fmszReaderNamesIsNULL)
1355 ret.cBytes = SCARD_AUTOALLOCATE;
1357 status = ret.ReturnCode =
1358 wrap(smartcard, SCardStatusW, operation->hCard,
1359 call->fmszReaderNamesIsNULL ?
nullptr : (LPWSTR)&mszReaderNames, &ret.cBytes,
1360 &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
1361 scard_log_status_error_wlog(smartcard->log,
"SCardStatusW", status);
1362 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cBytes == SCARD_AUTOALLOCATE))
1363 return SCARD_F_UNKNOWN_ERROR;
1366 if (status == SCARD_S_SUCCESS)
1368 if (!call->fmszReaderNamesIsNULL)
1369 ret.mszReaderNames = (BYTE*)mszReaderNames;
1371 ret.cbAtrLen = cbAtrLen;
1374 if (ret.cBytes != SCARD_AUTOALLOCATE)
1377 WINPR_ASSERT(ret.cBytes < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
1378 blen =
sizeof(WCHAR) * ret.cBytes;
1379 WINPR_ASSERT(blen <= UINT32_MAX);
1380 ret.cBytes = (UINT32)blen;
1383 status = smartcard_pack_status_return(out, &ret, TRUE);
1384 if (status != SCARD_S_SUCCESS)
1388 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1390 return ret.ReturnCode;
1393static LONG smartcard_Transmit_Call(scard_call_context* smartcard,
wStream* out,
1400 WINPR_ASSERT(smartcard);
1402 WINPR_ASSERT(operation);
1404 call = &operation->call.transmit;
1405 ret.cbRecvLength = 0;
1406 ret.pbRecvBuffer =
nullptr;
1408 if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
1410 if (call->cbRecvLength >= 66560)
1411 call->cbRecvLength = 66560;
1413 ret.cbRecvLength = call->cbRecvLength;
1414 ret.pbRecvBuffer = (BYTE*)malloc(ret.cbRecvLength);
1416 if (!ret.pbRecvBuffer)
1417 return STATUS_NO_MEMORY;
1420 ret.pioRecvPci = call->pioRecvPci;
1422 wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
1423 call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
1425 scard_log_status_error_wlog(smartcard->log,
"SCardTransmit", ret.ReturnCode);
1427 status = smartcard_pack_transmit_return(out, &ret);
1428 free(ret.pbRecvBuffer);
1430 if (status != SCARD_S_SUCCESS)
1432 return ret.ReturnCode;
1435static LONG smartcard_Control_Call(scard_call_context* smartcard,
wStream* out,
1442 WINPR_ASSERT(smartcard);
1444 WINPR_ASSERT(operation);
1446 call = &operation->call.control;
1447 ret.cbOutBufferSize = call->cbOutBufferSize;
1448 ret.pvOutBuffer = (BYTE*)malloc(call->cbOutBufferSize);
1450 if (!ret.pvOutBuffer)
1451 return SCARD_E_NO_MEMORY;
1454 wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
1455 call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
1456 scard_log_status_error_wlog(smartcard->log,
"SCardControl", ret.ReturnCode);
1457 status = smartcard_pack_control_return(out, &ret);
1459 free(ret.pvOutBuffer);
1460 if (status != SCARD_S_SUCCESS)
1462 return ret.ReturnCode;
1465static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard,
wStream* out,
1468 BOOL autoAllocate = FALSE;
1470 DWORD cbAttrLen = 0;
1471 LPBYTE pbAttr =
nullptr;
1475 WINPR_ASSERT(smartcard);
1476 WINPR_ASSERT(operation);
1478 call = &operation->call.getAttrib;
1480 if (!call->fpbAttrIsNULL)
1482 autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE);
1483 cbAttrLen = call->cbAttrLen;
1484 if (cbAttrLen && !autoAllocate)
1486 ret.pbAttr = (BYTE*)malloc(cbAttrLen);
1489 return SCARD_E_NO_MEMORY;
1492 pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
1496 wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
1497 scard_log_status_error_wlog(smartcard->log,
"SCardGetAttrib", ret.ReturnCode);
1498 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cbAttrLen == SCARD_AUTOALLOCATE))
1499 return SCARD_F_UNKNOWN_ERROR;
1501 ret.cbAttrLen = cbAttrLen;
1503 status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
1506 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
1512static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1518 WINPR_ASSERT(smartcard);
1520 WINPR_ASSERT(operation);
1522 call = &operation->call.setAttrib;
1524 ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
1526 scard_log_status_error_wlog(smartcard->log,
"SCardSetAttrib", ret.ReturnCode);
1527 smartcard_trace_long_return_int(smartcard->log, &ret,
"SetAttrib");
1529 return ret.ReturnCode;
1532static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard,
1533 WINPR_ATTR_UNUSED
wStream* out,
1536 LONG status = SCARD_S_SUCCESS;
1538 WINPR_ASSERT(smartcard);
1540 WINPR_UNUSED(operation);
1542 if (!smartcard->StartedEvent)
1543 smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
1545 if (!smartcard->StartedEvent)
1546 status = SCARD_E_NO_SERVICE;
1551static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard,
wStream* out,
1559 WINPR_ASSERT(smartcard);
1560 WINPR_ASSERT(operation);
1562 call = &operation->call.locateCardsByATRA;
1566 return STATUS_NO_MEMORY;
1568 for (UINT32 i = 0; i < call->cReaders; i++)
1571 state->szReader = call->rgReaderStates[i].szReader;
1572 state->dwCurrentState = call->rgReaderStates[i].dwCurrentState;
1573 state->dwEventState = call->rgReaderStates[i].dwEventState;
1574 state->cbAtr = call->rgReaderStates[i].cbAtr;
1575 CopyMemory(&(state->rgbAtr), &(call->rgReaderStates[i].rgbAtr), 36);
1578 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1579 0x000001F4, states, call->cReaders);
1581 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", status);
1582 for (UINT32 i = 0; i < call->cAtrs; i++)
1584 for (UINT32 j = 0; j < call->cReaders; j++)
1586 for (UINT32 k = 0; k < call->rgAtrMasks[i].cbAtr; k++)
1588 if ((call->rgAtrMasks[i].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]) !=
1589 (states[j].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]))
1594 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1599 ret.cReaders = call->cReaders;
1600 ret.rgReaderStates =
nullptr;
1602 if (ret.cReaders > 0)
1605 if (!ret.rgReaderStates)
1608 return STATUS_NO_MEMORY;
1611 for (UINT32 i = 0; i < ret.cReaders; i++)
1614 ret.rgReaderStates[i].dwCurrentState = state->dwCurrentState;
1615 ret.rgReaderStates[i].dwEventState = state->dwEventState;
1616 ret.rgReaderStates[i].cbAtr = state->cbAtr;
1617 CopyMemory(&(ret.rgReaderStates[i].rgbAtr), &(state->rgbAtr),
1618 sizeof(ret.rgReaderStates[i].rgbAtr));
1623 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1625 free(ret.rgReaderStates);
1626 if (status != SCARD_S_SUCCESS)
1628 return ret.ReturnCode;
1631LONG smartcard_irp_device_control_call(scard_call_context* ctx,
wStream* out, NTSTATUS* pIoStatus,
1636 size_t objectBufferLength = 0;
1640 WINPR_ASSERT(pIoStatus);
1641 WINPR_ASSERT(operation);
1643 const UINT32 ioControlCode = operation->ioControlCode;
1651 const size_t outMaxLen = MAX(2048, operation->outputBufferLength);
1652 if (!Stream_EnsureRemainingCapacity(out, outMaxLen))
1653 return SCARD_E_NO_MEMORY;
1656 Stream_Write_UINT32(out, 0);
1657 Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH);
1658 Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH);
1659 Stream_Write_UINT32(out, 0);
1662 switch (ioControlCode)
1664 case SCARD_IOCTL_ESTABLISHCONTEXT:
1665 result = smartcard_EstablishContext_Call(ctx, out, operation);
1668 case SCARD_IOCTL_RELEASECONTEXT:
1669 result = smartcard_ReleaseContext_Call(ctx, out, operation);
1672 case SCARD_IOCTL_ISVALIDCONTEXT:
1673 result = smartcard_IsValidContext_Call(ctx, out, operation);
1676 case SCARD_IOCTL_LISTREADERGROUPSA:
1677 result = smartcard_ListReaderGroupsA_Call(ctx, out, operation);
1680 case SCARD_IOCTL_LISTREADERGROUPSW:
1681 result = smartcard_ListReaderGroupsW_Call(ctx, out, operation);
1684 case SCARD_IOCTL_LISTREADERSA:
1685 result = smartcard_ListReadersA_Call(ctx, out, operation);
1688 case SCARD_IOCTL_LISTREADERSW:
1689 result = smartcard_ListReadersW_Call(ctx, out, operation);
1692 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1693 result = smartcard_IntroduceReaderGroupA_Call(ctx, out, operation);
1696 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1697 result = smartcard_IntroduceReaderGroupW_Call(ctx, out, operation);
1700 case SCARD_IOCTL_FORGETREADERGROUPA:
1701 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
1704 case SCARD_IOCTL_FORGETREADERGROUPW:
1705 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
1708 case SCARD_IOCTL_INTRODUCEREADERA:
1709 result = smartcard_IntroduceReaderA_Call(ctx, out, operation);
1712 case SCARD_IOCTL_INTRODUCEREADERW:
1713 result = smartcard_IntroduceReaderW_Call(ctx, out, operation);
1716 case SCARD_IOCTL_FORGETREADERA:
1717 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
1720 case SCARD_IOCTL_FORGETREADERW:
1721 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
1724 case SCARD_IOCTL_ADDREADERTOGROUPA:
1725 result = smartcard_AddReaderToGroupA_Call(ctx, out, operation);
1728 case SCARD_IOCTL_ADDREADERTOGROUPW:
1729 result = smartcard_AddReaderToGroupW_Call(ctx, out, operation);
1732 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1733 result = smartcard_RemoveReaderFromGroupA_Call(ctx, out, operation);
1736 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1737 result = smartcard_RemoveReaderFromGroupW_Call(ctx, out, operation);
1740 case SCARD_IOCTL_LOCATECARDSA:
1741 result = smartcard_LocateCardsA_Call(ctx, out, operation);
1744 case SCARD_IOCTL_LOCATECARDSW:
1745 result = smartcard_LocateCardsW_Call(ctx, out, operation);
1748 case SCARD_IOCTL_GETSTATUSCHANGEA:
1749 result = smartcard_GetStatusChangeA_Call(ctx, out, operation);
1752 case SCARD_IOCTL_GETSTATUSCHANGEW:
1753 result = smartcard_GetStatusChangeW_Call(ctx, out, operation);
1756 case SCARD_IOCTL_CANCEL:
1757 result = smartcard_Cancel_Call(ctx, out, operation);
1760 case SCARD_IOCTL_CONNECTA:
1761 result = smartcard_ConnectA_Call(ctx, out, operation);
1764 case SCARD_IOCTL_CONNECTW:
1765 result = smartcard_ConnectW_Call(ctx, out, operation);
1768 case SCARD_IOCTL_RECONNECT:
1769 result = smartcard_Reconnect_Call(ctx, out, operation);
1772 case SCARD_IOCTL_DISCONNECT:
1773 result = smartcard_Disconnect_Call(ctx, out, operation);
1776 case SCARD_IOCTL_BEGINTRANSACTION:
1777 result = smartcard_BeginTransaction_Call(ctx, out, operation);
1780 case SCARD_IOCTL_ENDTRANSACTION:
1781 result = smartcard_EndTransaction_Call(ctx, out, operation);
1784 case SCARD_IOCTL_STATE:
1785 result = smartcard_State_Call(ctx, out, operation);
1788 case SCARD_IOCTL_STATUSA:
1789 result = smartcard_StatusA_Call(ctx, out, operation);
1792 case SCARD_IOCTL_STATUSW:
1793 result = smartcard_StatusW_Call(ctx, out, operation);
1796 case SCARD_IOCTL_TRANSMIT:
1797 result = smartcard_Transmit_Call(ctx, out, operation);
1800 case SCARD_IOCTL_CONTROL:
1801 result = smartcard_Control_Call(ctx, out, operation);
1804 case SCARD_IOCTL_GETATTRIB:
1805 result = smartcard_GetAttrib_Call(ctx, out, operation);
1808 case SCARD_IOCTL_SETATTRIB:
1809 result = smartcard_SetAttrib_Call(ctx, out, operation);
1812 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
1813 result = smartcard_AccessStartedEvent_Call(ctx, out, operation);
1816 case SCARD_IOCTL_LOCATECARDSBYATRA:
1817 result = smartcard_LocateCardsByATRA_Call(ctx, out, operation);
1820 case SCARD_IOCTL_LOCATECARDSBYATRW:
1821 result = smartcard_LocateCardsW_Call(ctx, out, operation);
1824 case SCARD_IOCTL_READCACHEA:
1825 result = smartcard_ReadCacheA_Call(ctx, out, operation);
1828 case SCARD_IOCTL_READCACHEW:
1829 result = smartcard_ReadCacheW_Call(ctx, out, operation);
1832 case SCARD_IOCTL_WRITECACHEA:
1833 result = smartcard_WriteCacheA_Call(ctx, out, operation);
1836 case SCARD_IOCTL_WRITECACHEW:
1837 result = smartcard_WriteCacheW_Call(ctx, out, operation);
1840 case SCARD_IOCTL_GETTRANSMITCOUNT:
1841 result = smartcard_GetTransmitCount_Call(ctx, out, operation);
1844 case SCARD_IOCTL_RELEASETARTEDEVENT:
1845 result = smartcard_ReleaseStartedEvent_Call(ctx, out, operation);
1848 case SCARD_IOCTL_GETREADERICON:
1849 result = smartcard_GetReaderIcon_Call(ctx, out, operation);
1852 case SCARD_IOCTL_GETDEVICETYPEID:
1853 result = smartcard_GetDeviceTypeId_Call(ctx, out, operation);
1857 result = STATUS_UNSUCCESSFUL;
1867 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
1868 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
1870 offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
1871 const LONG rc = smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
1872 if (rc != SCARD_S_SUCCESS)
1876 if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
1877 (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
1878 (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
1880 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
1881 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
1884 *pIoStatus = STATUS_SUCCESS;
1886 if ((result & 0xC0000000L) == 0xC0000000L)
1889 *pIoStatus = result;
1891 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
1892 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
1895 Stream_SealLength(out);
1896 size_t outputBufferLength = Stream_Length(out);
1897 size_t dataEndPos = outputBufferLength;
1899 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1900 outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1901 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1902 objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
1903 WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
1904 WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
1905 if (!Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH))
1906 return SCARD_E_BAD_SEEK;
1915 if (outputBufferLength > operation->outputBufferLength)
1917 WLog_Print(ctx->log, WLOG_DEBUG,
1918 "IRP warn: expected outputBufferLength %" PRIuz
", but current limit %" PRIu32
1919 ", respond with STATUS_BUFFER_TOO_SMALL for retransmit with larger buffer",
1920 outputBufferLength, operation->outputBufferLength);
1922 *pIoStatus = STATUS_BUFFER_TOO_SMALL;
1923 result = *pIoStatus;
1924 outputBufferLength = 0;
1925 objectBufferLength = 0;
1929 WLog_Print(ctx->log, WLOG_TRACE,
"IRP trace: outputBufferLength %" PRIuz
", limit %" PRIu32,
1930 outputBufferLength, operation->outputBufferLength);
1934 Stream_Write_UINT32(out, (UINT32)outputBufferLength);
1935 smartcard_pack_common_type_header(out);
1936 smartcard_pack_private_type_header(
1937 out, (UINT32)objectBufferLength);
1938 Stream_Write_INT32(out, result);
1939 if (result == STATUS_BUFFER_TOO_SMALL)
1940 Stream_SealLength(out);
1941 else if (!Stream_SetPosition(out, dataEndPos))
1942 return SCARD_E_BAD_SEEK;
1943 return SCARD_S_SUCCESS;
1946void context_free(
void* arg)
1948 struct s_scard_context_element* element = arg;
1952 if (element->fn_free)
1953 element->fn_free(element->context);
1957#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
1958scard_call_context* smartcard_call_context_new(
const rdpSettings* settings)
1961 if (!inst || !inst->context)
1963 return smartcard_call_context_new_with_context(inst->context);
1967scard_call_context* smartcard_call_context_new_with_context(rdpContext* context)
1969 WINPR_ASSERT(context);
1970 scard_call_context* ctx = calloc(1,
sizeof(scard_call_context));
1974 ctx->context = context;
1976 const rdpSettings* settings = context->settings;
1977 WINPR_ASSERT(settings);
1979 ctx->log = WLog_Get(SCARD_TAG);
1980 WINPR_ASSERT(ctx->log);
1982 ctx->stopEvent = CreateEventA(
nullptr, TRUE, FALSE,
nullptr);
1983 if (!ctx->stopEvent)
1986 ctx->names = LinkedList_New();
1990#if defined(WITH_SMARTCARD_EMULATE)
1994 if (ctx->useEmulatedCard)
1996#if defined(WITH_SMARTCARD_EMULATE)
1997 ctx->emulation = Emulate_New(settings);
1998 if (!ctx->emulation)
2001 WLog_Print(ctx->log, WLOG_ERROR,
"Smartcard emulation requested, but not supported!");
2010 ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
2012 if (!ctx->hWinSCardLibrary)
2014 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard library: '%s'",
2019 if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
2021 ctx->pWinSCardApi = &ctx->WinSCardApi;
2025 ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
2028 if (!ctx->pWinSCardApi)
2030 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard API!");
2035 ctx->rgSCardContextList = HashTable_New(FALSE);
2036 if (!ctx->rgSCardContextList)
2040 wObject* obj = HashTable_ValueObject(ctx->rgSCardContextList);
2047 WINPR_PRAGMA_DIAG_PUSH
2048 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2049 smartcard_call_context_free(ctx);
2050 WINPR_PRAGMA_DIAG_POP
2054void smartcard_call_context_free(scard_call_context* ctx)
2059 smartcard_call_context_signal_stop(ctx, FALSE);
2061 LinkedList_Free(ctx->names);
2062 if (ctx->StartedEvent)
2064 WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
2065 wrap_raw(ctx, SCardReleaseStartedEvent);
2068 if (ctx->useEmulatedCard)
2070#ifdef WITH_SMARTCARD_EMULATE
2073 Emulate_Free(ctx->emulation);
2074 ctx->emulation =
nullptr;
2079 if (ctx->hWinSCardLibrary)
2082 FreeLibrary(ctx->hWinSCardLibrary);
2083 ctx->hWinSCardLibrary =
nullptr;
2086 ctx->pWinSCardApi =
nullptr;
2088 HashTable_Free(ctx->rgSCardContextList);
2089 (void)CloseHandle(ctx->stopEvent);
2093BOOL smartcard_call_context_add(scard_call_context* ctx,
const char* name)
2097 return LinkedList_AddLast(ctx->names, name);
2100BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2103 if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
2105 wrap(ctx, SCardCancel, hContext);
2110BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2113 wrap(ctx, SCardReleaseContext, hContext);
2117BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
2122 HashTable_Clear(ctx->rgSCardContextList);
2126BOOL smarcard_call_set_callbacks(scard_call_context* ctx,
void* userdata,
2127 void* (*fn_new)(
void*, SCARDCONTEXT),
void (*fn_free)(
void*))
2130 ctx->userdata = userdata;
2131 ctx->fn_new = fn_new;
2132 ctx->fn_free = fn_free;
2136void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2138 struct s_scard_context_element* element =
nullptr;
2141 element = HashTable_GetItemValue(ctx->rgSCardContextList, (
void*)hContext);
2144 return element->context;
2147BOOL smartcard_call_is_configured(scard_call_context* ctx)
2151#if defined(WITH_SMARTCARD_EMULATE)
2152 if (ctx->useEmulatedCard)
2153 return Emulate_IsConfigured(ctx->emulation);
2159BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
2163 if (!ctx->stopEvent)
2167 return ResetEvent(ctx->stopEvent);
2169 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