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);
758 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
759 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
761 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheA", ret.ReturnCode);
764 status = smartcard_pack_read_cache_return(out, &ret);
766 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
769 if (status != SCARD_S_SUCCESS)
772 return ret.ReturnCode;
775static LONG smartcard_ReadCacheW_Call(scard_call_context* smartcard,
wStream* out,
782 WINPR_ASSERT(smartcard);
784 WINPR_ASSERT(operation);
786 call = &operation->call.readCacheW;
788 if (!call->Common.fPbDataIsNULL)
789 ret.cbDataLen = SCARD_AUTOALLOCATE;
792 wrap(smartcard, SCardReadCacheW, operation->hContext, call->Common.CardIdentifier,
793 call->Common.FreshnessCounter, call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
795 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
796 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
798 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheW", ret.ReturnCode);
801 status = smartcard_pack_read_cache_return(out, &ret);
803 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
805 if (status != SCARD_S_SUCCESS)
808 return ret.ReturnCode;
811static LONG smartcard_WriteCacheA_Call(scard_call_context* smartcard,
812 WINPR_ATTR_UNUSED
wStream* out,
818 WINPR_ASSERT(smartcard);
820 WINPR_ASSERT(operation);
822 call = &operation->call.writeCacheA;
824 ret.ReturnCode = wrap(smartcard, SCardWriteCacheA, operation->hContext,
825 call->Common.CardIdentifier, call->Common.FreshnessCounter,
826 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
827 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheA", ret.ReturnCode);
828 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheA");
829 return ret.ReturnCode;
832static LONG smartcard_WriteCacheW_Call(scard_call_context* smartcard,
833 WINPR_ATTR_UNUSED
wStream* out,
839 WINPR_ASSERT(smartcard);
841 WINPR_ASSERT(operation);
843 call = &operation->call.writeCacheW;
845 ret.ReturnCode = wrap(smartcard, SCardWriteCacheW, operation->hContext,
846 call->Common.CardIdentifier, call->Common.FreshnessCounter,
847 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
848 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheW", ret.ReturnCode);
849 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheW");
850 return ret.ReturnCode;
853static LONG smartcard_GetTransmitCount_Call(scard_call_context* smartcard,
wStream* out,
859 WINPR_ASSERT(smartcard);
861 WINPR_ASSERT(operation);
863 ret.ReturnCode = wrap(smartcard, SCardGetTransmitCount, operation->hCard, &ret.cTransmitCount);
864 scard_log_status_error_wlog(smartcard->log,
"SCardGetTransmitCount", ret.ReturnCode);
865 status = smartcard_pack_get_transmit_count_return(out, &ret);
866 if (status != SCARD_S_SUCCESS)
869 return ret.ReturnCode;
872static LONG smartcard_ReleaseStartedEvent_Call(scard_call_context* smartcard,
wStream* out,
875 WINPR_UNUSED(smartcard);
877 WINPR_UNUSED(operation);
879 WLog_Print(smartcard->log, WLOG_WARN,
880 "According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
881 "this is not supported?!?");
882 return SCARD_E_UNSUPPORTED_FEATURE;
885static LONG smartcard_GetReaderIcon_Call(scard_call_context* smartcard,
wStream* out,
892 WINPR_ASSERT(smartcard);
894 WINPR_ASSERT(operation);
896 call = &operation->call.getReaderIcon;
898 ret.cbDataLen = SCARD_AUTOALLOCATE;
899 ret.ReturnCode = wrap(smartcard, SCardGetReaderIconW, operation->hContext, call->szReaderName,
900 (LPBYTE)&ret.pbData, &ret.cbDataLen);
901 scard_log_status_error_wlog(smartcard->log,
"SCardGetReaderIconW", ret.ReturnCode);
902 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cbDataLen == SCARD_AUTOALLOCATE))
903 return SCARD_F_UNKNOWN_ERROR;
905 status = smartcard_pack_get_reader_icon_return(out, &ret);
906 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
907 if (status != SCARD_S_SUCCESS)
910 return ret.ReturnCode;
913static LONG smartcard_GetDeviceTypeId_Call(scard_call_context* smartcard,
wStream* out,
920 WINPR_ASSERT(smartcard);
922 WINPR_ASSERT(operation);
924 call = &operation->call.getDeviceTypeId;
926 ret.ReturnCode = wrap(smartcard, SCardGetDeviceTypeIdW, operation->hContext, call->szReaderName,
928 scard_log_status_error_wlog(smartcard->log,
"SCardGetDeviceTypeIdW", ret.ReturnCode);
930 status = smartcard_pack_device_type_id_return(out, &ret);
931 if (status != SCARD_S_SUCCESS)
934 return ret.ReturnCode;
937static BOOL smartcard_context_was_aborted(scard_call_context* smartcard)
939 WINPR_ASSERT(smartcard);
941 HANDLE handles[] = { smartcard->stopEvent, freerdp_abort_event(smartcard->context) };
942 const DWORD rc = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, 0);
943 return (rc >= WAIT_OBJECT_0) && (rc <= WAIT_OBJECT_0 + ARRAYSIZE(handles));
946static LONG smartcard_GetStatusChangeA_Call(scard_call_context* smartcard,
wStream* out,
949 LONG status = STATUS_NO_MEMORY;
951 const DWORD dwTimeStep = 100;
956 WINPR_ASSERT(smartcard);
958 WINPR_ASSERT(operation);
960 call = &operation->call.getStatusChangeA;
961 dwTimeOut = call->dwTimeOut;
963 if (call->cReaders > 0)
965 ret.cReaders = call->cReaders;
968 if (!rgReaderStates || !ret.rgReaderStates)
972 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
974 if (call->cReaders > 0)
975 memcpy(rgReaderStates, call->rgReaderStates,
977 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
978 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
979 if (ret.ReturnCode != SCARD_E_TIMEOUT)
981 if (smartcard_context_was_aborted(smartcard))
983 if (dwTimeOut != INFINITE)
986 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", ret.ReturnCode);
988 for (UINT32 index = 0; index < ret.cReaders; index++)
993 rout->dwCurrentState = cur->dwCurrentState;
994 rout->dwEventState = cur->dwEventState;
995 rout->cbAtr = cur->cbAtr;
996 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
999 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1001 free(ret.rgReaderStates);
1002 free(rgReaderStates);
1003 if (status != SCARD_S_SUCCESS)
1005 return ret.ReturnCode;
1008static LONG smartcard_GetStatusChangeW_Call(scard_call_context* smartcard,
wStream* out,
1011 LONG status = STATUS_NO_MEMORY;
1012 DWORD dwTimeOut = 0;
1013 const DWORD dwTimeStep = 100;
1017 WINPR_ASSERT(smartcard);
1019 WINPR_ASSERT(operation);
1022 dwTimeOut = call->dwTimeOut;
1024 if (call->cReaders > 0)
1026 ret.cReaders = call->cReaders;
1029 if (!rgReaderStates || !ret.rgReaderStates)
1033 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
1035 if (call->cReaders > 0)
1036 memcpy(rgReaderStates, call->rgReaderStates,
1039 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
1040 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
1042 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1044 if (smartcard_context_was_aborted(smartcard))
1046 if (dwTimeOut != INFINITE)
1049 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeW", ret.ReturnCode);
1051 for (UINT32 index = 0; index < ret.cReaders; index++)
1056 rout->dwCurrentState = cur->dwCurrentState;
1057 rout->dwEventState = cur->dwEventState;
1058 rout->cbAtr = cur->cbAtr;
1059 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1062 status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
1064 free(ret.rgReaderStates);
1065 free(rgReaderStates);
1066 if (status != SCARD_S_SUCCESS)
1068 return ret.ReturnCode;
1071static LONG smartcard_Cancel_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1076 WINPR_ASSERT(smartcard);
1078 WINPR_ASSERT(operation);
1080 ret.ReturnCode = wrap(smartcard, SCardCancel, operation->hContext);
1081 scard_log_status_error_wlog(smartcard->log,
"SCardCancel", ret.ReturnCode);
1082 smartcard_trace_long_return_int(smartcard->log, &ret,
"Cancel");
1083 return ret.ReturnCode;
1086static LONG smartcard_ConnectA_Call(scard_call_context* smartcard,
wStream* out,
1090 SCARDHANDLE hCard = 0;
1094 WINPR_ASSERT(smartcard);
1096 WINPR_ASSERT(operation);
1098 call = &operation->call.connectA;
1100 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1101 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1103 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1106 ret.ReturnCode = wrap(smartcard, SCardConnectA, operation->hContext, (
char*)call->szReader,
1107 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1108 &ret.dwActiveProtocol);
1109 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1110 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1112 status = smartcard_pack_connect_return(out, &ret);
1113 if (status != SCARD_S_SUCCESS)
1116 status = ret.ReturnCode;
1122static LONG smartcard_ConnectW_Call(scard_call_context* smartcard,
wStream* out,
1126 SCARDHANDLE hCard = 0;
1130 WINPR_ASSERT(smartcard);
1132 WINPR_ASSERT(operation);
1134 call = &operation->call.connectW;
1136 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1137 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1139 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1142 ret.ReturnCode = wrap(smartcard, SCardConnectW, operation->hContext, (WCHAR*)call->szReader,
1143 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1144 &ret.dwActiveProtocol);
1145 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1146 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1148 status = smartcard_pack_connect_return(out, &ret);
1149 if (status != SCARD_S_SUCCESS)
1152 status = ret.ReturnCode;
1158static LONG smartcard_Reconnect_Call(scard_call_context* smartcard,
wStream* out,
1165 WINPR_ASSERT(smartcard);
1167 WINPR_ASSERT(operation);
1169 call = &operation->call.reconnect;
1171 wrap(smartcard, SCardReconnect, operation->hCard, call->dwShareMode,
1172 call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
1173 scard_log_status_error_wlog(smartcard->log,
"SCardReconnect", ret.ReturnCode);
1174 status = smartcard_pack_reconnect_return(out, &ret);
1175 if (status != SCARD_S_SUCCESS)
1178 return ret.ReturnCode;
1181static LONG smartcard_Disconnect_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1187 WINPR_ASSERT(smartcard);
1189 WINPR_ASSERT(operation);
1191 call = &operation->call.hCardAndDisposition;
1193 ret.ReturnCode = wrap(smartcard, SCardDisconnect, operation->hCard, call->dwDisposition);
1194 scard_log_status_error_wlog(smartcard->log,
"SCardDisconnect", ret.ReturnCode);
1195 smartcard_trace_long_return_int(smartcard->log, &ret,
"Disconnect");
1197 return ret.ReturnCode;
1200static LONG smartcard_BeginTransaction_Call(scard_call_context* smartcard,
1201 WINPR_ATTR_UNUSED
wStream* out,
1206 WINPR_ASSERT(smartcard);
1208 WINPR_ASSERT(operation);
1210 ret.ReturnCode = wrap(smartcard, SCardBeginTransaction, operation->hCard);
1211 scard_log_status_error_wlog(smartcard->log,
"SCardBeginTransaction", ret.ReturnCode);
1212 smartcard_trace_long_return_int(smartcard->log, &ret,
"BeginTransaction");
1213 return ret.ReturnCode;
1216static LONG smartcard_EndTransaction_Call(scard_call_context* smartcard,
1217 WINPR_ATTR_UNUSED
wStream* out,
1223 WINPR_ASSERT(smartcard);
1225 WINPR_ASSERT(operation);
1227 call = &operation->call.hCardAndDisposition;
1229 ret.ReturnCode = wrap(smartcard, SCardEndTransaction, operation->hCard, call->dwDisposition);
1230 scard_log_status_error_wlog(smartcard->log,
"SCardEndTransaction", ret.ReturnCode);
1231 smartcard_trace_long_return_int(smartcard->log, &ret,
"EndTransaction");
1232 return ret.ReturnCode;
1235static LONG smartcard_State_Call(scard_call_context* smartcard,
wStream* out,
1241 WINPR_ASSERT(smartcard);
1243 WINPR_ASSERT(operation);
1245 ret.cbAtrLen = SCARD_ATR_LENGTH;
1246 ret.ReturnCode = wrap(smartcard, SCardState, operation->hCard, &ret.dwState, &ret.dwProtocol,
1247 (BYTE*)&ret.rgAtr, &ret.cbAtrLen);
1249 scard_log_status_error_wlog(smartcard->log,
"SCardState", ret.ReturnCode);
1250 status = smartcard_pack_state_return(out, &ret);
1251 if (status != SCARD_S_SUCCESS)
1254 return ret.ReturnCode;
1257static LONG smartcard_StatusA_Call(scard_call_context* smartcard,
wStream* out,
1262 DWORD cchReaderLen = 0;
1264 LPSTR mszReaderNames =
nullptr;
1267 WINPR_ASSERT(smartcard);
1269 WINPR_ASSERT(operation);
1271 call = &operation->call.status;
1273 call->cbAtrLen = 32;
1274 cbAtrLen = call->cbAtrLen;
1276 if (call->fmszReaderNamesIsNULL)
1279 cchReaderLen = SCARD_AUTOALLOCATE;
1281 status = ret.ReturnCode =
1282 wrap(smartcard, SCardStatusA, operation->hCard,
1283 call->fmszReaderNamesIsNULL ?
nullptr : (LPSTR)&mszReaderNames, &cchReaderLen,
1284 &ret.dwState, &ret.dwProtocol, cbAtrLen ? (BYTE*)&ret.pbAtr : nullptr, &cbAtrLen);
1286 scard_log_status_error_wlog(smartcard->log,
"SCardStatusA", status);
1287 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchReaderLen == SCARD_AUTOALLOCATE))
1288 return SCARD_F_UNKNOWN_ERROR;
1290 if (status == SCARD_S_SUCCESS)
1292 if (!call->fmszReaderNamesIsNULL)
1293 ret.mszReaderNames = (BYTE*)mszReaderNames;
1295 ret.cBytes = cchReaderLen;
1298 ret.cbAtrLen = cbAtrLen;
1301 status = smartcard_pack_status_return(out, &ret, FALSE);
1304 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1306 if (status != SCARD_S_SUCCESS)
1308 return ret.ReturnCode;
1311static LONG smartcard_StatusW_Call(scard_call_context* smartcard,
wStream* out,
1316 LPWSTR mszReaderNames =
nullptr;
1320 WINPR_ASSERT(smartcard);
1322 WINPR_ASSERT(operation);
1324 call = &operation->call.status;
1330 cbAtrLen = call->cbAtrLen = 32;
1332 if (call->fmszReaderNamesIsNULL)
1335 ret.cBytes = SCARD_AUTOALLOCATE;
1337 status = ret.ReturnCode =
1338 wrap(smartcard, SCardStatusW, operation->hCard,
1339 call->fmszReaderNamesIsNULL ?
nullptr : (LPWSTR)&mszReaderNames, &ret.cBytes,
1340 &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
1341 scard_log_status_error_wlog(smartcard->log,
"SCardStatusW", status);
1342 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cBytes == SCARD_AUTOALLOCATE))
1343 return SCARD_F_UNKNOWN_ERROR;
1346 if (status == SCARD_S_SUCCESS)
1348 if (!call->fmszReaderNamesIsNULL)
1349 ret.mszReaderNames = (BYTE*)mszReaderNames;
1351 ret.cbAtrLen = cbAtrLen;
1354 if (ret.cBytes != SCARD_AUTOALLOCATE)
1357 WINPR_ASSERT(ret.cBytes < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
1358 blen =
sizeof(WCHAR) * ret.cBytes;
1359 WINPR_ASSERT(blen <= UINT32_MAX);
1360 ret.cBytes = (UINT32)blen;
1363 status = smartcard_pack_status_return(out, &ret, TRUE);
1364 if (status != SCARD_S_SUCCESS)
1368 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1370 return ret.ReturnCode;
1373static LONG smartcard_Transmit_Call(scard_call_context* smartcard,
wStream* out,
1380 WINPR_ASSERT(smartcard);
1382 WINPR_ASSERT(operation);
1384 call = &operation->call.transmit;
1385 ret.cbRecvLength = 0;
1386 ret.pbRecvBuffer =
nullptr;
1388 if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
1390 if (call->cbRecvLength >= 66560)
1391 call->cbRecvLength = 66560;
1393 ret.cbRecvLength = call->cbRecvLength;
1394 ret.pbRecvBuffer = (BYTE*)malloc(ret.cbRecvLength);
1396 if (!ret.pbRecvBuffer)
1397 return STATUS_NO_MEMORY;
1400 ret.pioRecvPci = call->pioRecvPci;
1402 wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
1403 call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
1405 scard_log_status_error_wlog(smartcard->log,
"SCardTransmit", ret.ReturnCode);
1407 status = smartcard_pack_transmit_return(out, &ret);
1408 free(ret.pbRecvBuffer);
1410 if (status != SCARD_S_SUCCESS)
1412 return ret.ReturnCode;
1415static LONG smartcard_Control_Call(scard_call_context* smartcard,
wStream* out,
1422 WINPR_ASSERT(smartcard);
1424 WINPR_ASSERT(operation);
1426 call = &operation->call.control;
1427 ret.cbOutBufferSize = call->cbOutBufferSize;
1428 ret.pvOutBuffer = (BYTE*)malloc(call->cbOutBufferSize);
1430 if (!ret.pvOutBuffer)
1431 return SCARD_E_NO_MEMORY;
1434 wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
1435 call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
1436 scard_log_status_error_wlog(smartcard->log,
"SCardControl", ret.ReturnCode);
1437 status = smartcard_pack_control_return(out, &ret);
1439 free(ret.pvOutBuffer);
1440 if (status != SCARD_S_SUCCESS)
1442 return ret.ReturnCode;
1445static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard,
wStream* out,
1448 BOOL autoAllocate = FALSE;
1450 DWORD cbAttrLen = 0;
1451 LPBYTE pbAttr =
nullptr;
1455 WINPR_ASSERT(smartcard);
1456 WINPR_ASSERT(operation);
1458 call = &operation->call.getAttrib;
1460 if (!call->fpbAttrIsNULL)
1462 autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE);
1463 cbAttrLen = call->cbAttrLen;
1464 if (cbAttrLen && !autoAllocate)
1466 ret.pbAttr = (BYTE*)malloc(cbAttrLen);
1469 return SCARD_E_NO_MEMORY;
1472 pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
1476 wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
1477 scard_log_status_error_wlog(smartcard->log,
"SCardGetAttrib", ret.ReturnCode);
1478 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cbAttrLen == SCARD_AUTOALLOCATE))
1479 return SCARD_F_UNKNOWN_ERROR;
1481 ret.cbAttrLen = cbAttrLen;
1483 status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
1486 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
1492static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1498 WINPR_ASSERT(smartcard);
1500 WINPR_ASSERT(operation);
1502 call = &operation->call.setAttrib;
1504 ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
1506 scard_log_status_error_wlog(smartcard->log,
"SCardSetAttrib", ret.ReturnCode);
1507 smartcard_trace_long_return_int(smartcard->log, &ret,
"SetAttrib");
1509 return ret.ReturnCode;
1512static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard,
1513 WINPR_ATTR_UNUSED
wStream* out,
1516 LONG status = SCARD_S_SUCCESS;
1518 WINPR_ASSERT(smartcard);
1520 WINPR_UNUSED(operation);
1522 if (!smartcard->StartedEvent)
1523 smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
1525 if (!smartcard->StartedEvent)
1526 status = SCARD_E_NO_SERVICE;
1531static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard,
wStream* out,
1539 WINPR_ASSERT(smartcard);
1540 WINPR_ASSERT(operation);
1542 call = &operation->call.locateCardsByATRA;
1546 return STATUS_NO_MEMORY;
1548 for (UINT32 i = 0; i < call->cReaders; i++)
1551 state->szReader = call->rgReaderStates[i].szReader;
1552 state->dwCurrentState = call->rgReaderStates[i].dwCurrentState;
1553 state->dwEventState = call->rgReaderStates[i].dwEventState;
1554 state->cbAtr = call->rgReaderStates[i].cbAtr;
1555 CopyMemory(&(state->rgbAtr), &(call->rgReaderStates[i].rgbAtr), 36);
1558 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1559 0x000001F4, states, call->cReaders);
1561 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", status);
1562 for (UINT32 i = 0; i < call->cAtrs; i++)
1564 for (UINT32 j = 0; j < call->cReaders; j++)
1566 for (UINT32 k = 0; k < call->rgAtrMasks[i].cbAtr; k++)
1568 if ((call->rgAtrMasks[i].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]) !=
1569 (states[j].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]))
1574 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1579 ret.cReaders = call->cReaders;
1580 ret.rgReaderStates =
nullptr;
1582 if (ret.cReaders > 0)
1585 if (!ret.rgReaderStates)
1588 return STATUS_NO_MEMORY;
1591 for (UINT32 i = 0; i < ret.cReaders; i++)
1594 ret.rgReaderStates[i].dwCurrentState = state->dwCurrentState;
1595 ret.rgReaderStates[i].dwEventState = state->dwEventState;
1596 ret.rgReaderStates[i].cbAtr = state->cbAtr;
1597 CopyMemory(&(ret.rgReaderStates[i].rgbAtr), &(state->rgbAtr),
1598 sizeof(ret.rgReaderStates[i].rgbAtr));
1603 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1605 free(ret.rgReaderStates);
1606 if (status != SCARD_S_SUCCESS)
1608 return ret.ReturnCode;
1611LONG smartcard_irp_device_control_call(scard_call_context* ctx,
wStream* out, NTSTATUS* pIoStatus,
1616 size_t objectBufferLength = 0;
1620 WINPR_ASSERT(pIoStatus);
1621 WINPR_ASSERT(operation);
1623 const UINT32 ioControlCode = operation->ioControlCode;
1631 const size_t outMaxLen = MAX(2048, operation->outputBufferLength);
1632 if (!Stream_EnsureRemainingCapacity(out, outMaxLen))
1633 return SCARD_E_NO_MEMORY;
1636 Stream_Write_UINT32(out, 0);
1637 Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH);
1638 Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH);
1639 Stream_Write_UINT32(out, 0);
1642 switch (ioControlCode)
1644 case SCARD_IOCTL_ESTABLISHCONTEXT:
1645 result = smartcard_EstablishContext_Call(ctx, out, operation);
1648 case SCARD_IOCTL_RELEASECONTEXT:
1649 result = smartcard_ReleaseContext_Call(ctx, out, operation);
1652 case SCARD_IOCTL_ISVALIDCONTEXT:
1653 result = smartcard_IsValidContext_Call(ctx, out, operation);
1656 case SCARD_IOCTL_LISTREADERGROUPSA:
1657 result = smartcard_ListReaderGroupsA_Call(ctx, out, operation);
1660 case SCARD_IOCTL_LISTREADERGROUPSW:
1661 result = smartcard_ListReaderGroupsW_Call(ctx, out, operation);
1664 case SCARD_IOCTL_LISTREADERSA:
1665 result = smartcard_ListReadersA_Call(ctx, out, operation);
1668 case SCARD_IOCTL_LISTREADERSW:
1669 result = smartcard_ListReadersW_Call(ctx, out, operation);
1672 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1673 result = smartcard_IntroduceReaderGroupA_Call(ctx, out, operation);
1676 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1677 result = smartcard_IntroduceReaderGroupW_Call(ctx, out, operation);
1680 case SCARD_IOCTL_FORGETREADERGROUPA:
1681 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
1684 case SCARD_IOCTL_FORGETREADERGROUPW:
1685 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
1688 case SCARD_IOCTL_INTRODUCEREADERA:
1689 result = smartcard_IntroduceReaderA_Call(ctx, out, operation);
1692 case SCARD_IOCTL_INTRODUCEREADERW:
1693 result = smartcard_IntroduceReaderW_Call(ctx, out, operation);
1696 case SCARD_IOCTL_FORGETREADERA:
1697 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
1700 case SCARD_IOCTL_FORGETREADERW:
1701 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
1704 case SCARD_IOCTL_ADDREADERTOGROUPA:
1705 result = smartcard_AddReaderToGroupA_Call(ctx, out, operation);
1708 case SCARD_IOCTL_ADDREADERTOGROUPW:
1709 result = smartcard_AddReaderToGroupW_Call(ctx, out, operation);
1712 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1713 result = smartcard_RemoveReaderFromGroupA_Call(ctx, out, operation);
1716 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1717 result = smartcard_RemoveReaderFromGroupW_Call(ctx, out, operation);
1720 case SCARD_IOCTL_LOCATECARDSA:
1721 result = smartcard_LocateCardsA_Call(ctx, out, operation);
1724 case SCARD_IOCTL_LOCATECARDSW:
1725 result = smartcard_LocateCardsW_Call(ctx, out, operation);
1728 case SCARD_IOCTL_GETSTATUSCHANGEA:
1729 result = smartcard_GetStatusChangeA_Call(ctx, out, operation);
1732 case SCARD_IOCTL_GETSTATUSCHANGEW:
1733 result = smartcard_GetStatusChangeW_Call(ctx, out, operation);
1736 case SCARD_IOCTL_CANCEL:
1737 result = smartcard_Cancel_Call(ctx, out, operation);
1740 case SCARD_IOCTL_CONNECTA:
1741 result = smartcard_ConnectA_Call(ctx, out, operation);
1744 case SCARD_IOCTL_CONNECTW:
1745 result = smartcard_ConnectW_Call(ctx, out, operation);
1748 case SCARD_IOCTL_RECONNECT:
1749 result = smartcard_Reconnect_Call(ctx, out, operation);
1752 case SCARD_IOCTL_DISCONNECT:
1753 result = smartcard_Disconnect_Call(ctx, out, operation);
1756 case SCARD_IOCTL_BEGINTRANSACTION:
1757 result = smartcard_BeginTransaction_Call(ctx, out, operation);
1760 case SCARD_IOCTL_ENDTRANSACTION:
1761 result = smartcard_EndTransaction_Call(ctx, out, operation);
1764 case SCARD_IOCTL_STATE:
1765 result = smartcard_State_Call(ctx, out, operation);
1768 case SCARD_IOCTL_STATUSA:
1769 result = smartcard_StatusA_Call(ctx, out, operation);
1772 case SCARD_IOCTL_STATUSW:
1773 result = smartcard_StatusW_Call(ctx, out, operation);
1776 case SCARD_IOCTL_TRANSMIT:
1777 result = smartcard_Transmit_Call(ctx, out, operation);
1780 case SCARD_IOCTL_CONTROL:
1781 result = smartcard_Control_Call(ctx, out, operation);
1784 case SCARD_IOCTL_GETATTRIB:
1785 result = smartcard_GetAttrib_Call(ctx, out, operation);
1788 case SCARD_IOCTL_SETATTRIB:
1789 result = smartcard_SetAttrib_Call(ctx, out, operation);
1792 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
1793 result = smartcard_AccessStartedEvent_Call(ctx, out, operation);
1796 case SCARD_IOCTL_LOCATECARDSBYATRA:
1797 result = smartcard_LocateCardsByATRA_Call(ctx, out, operation);
1800 case SCARD_IOCTL_LOCATECARDSBYATRW:
1801 result = smartcard_LocateCardsW_Call(ctx, out, operation);
1804 case SCARD_IOCTL_READCACHEA:
1805 result = smartcard_ReadCacheA_Call(ctx, out, operation);
1808 case SCARD_IOCTL_READCACHEW:
1809 result = smartcard_ReadCacheW_Call(ctx, out, operation);
1812 case SCARD_IOCTL_WRITECACHEA:
1813 result = smartcard_WriteCacheA_Call(ctx, out, operation);
1816 case SCARD_IOCTL_WRITECACHEW:
1817 result = smartcard_WriteCacheW_Call(ctx, out, operation);
1820 case SCARD_IOCTL_GETTRANSMITCOUNT:
1821 result = smartcard_GetTransmitCount_Call(ctx, out, operation);
1824 case SCARD_IOCTL_RELEASETARTEDEVENT:
1825 result = smartcard_ReleaseStartedEvent_Call(ctx, out, operation);
1828 case SCARD_IOCTL_GETREADERICON:
1829 result = smartcard_GetReaderIcon_Call(ctx, out, operation);
1832 case SCARD_IOCTL_GETDEVICETYPEID:
1833 result = smartcard_GetDeviceTypeId_Call(ctx, out, operation);
1837 result = STATUS_UNSUCCESSFUL;
1847 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
1848 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
1850 offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
1851 const LONG rc = smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
1852 if (rc != SCARD_S_SUCCESS)
1856 if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
1857 (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
1858 (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
1860 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
1861 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
1864 *pIoStatus = STATUS_SUCCESS;
1866 if ((result & 0xC0000000L) == 0xC0000000L)
1869 *pIoStatus = result;
1871 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
1872 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
1875 Stream_SealLength(out);
1876 size_t outputBufferLength = Stream_Length(out);
1877 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1878 outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1879 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1880 objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
1881 WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
1882 WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
1883 if (!Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH))
1884 return SCARD_E_BAD_SEEK;
1893 if (outputBufferLength > operation->outputBufferLength)
1895 WLog_Print(ctx->log, WLOG_WARN,
1896 "IRP warn: expected outputBufferLength %" PRIu32
", but current limit %" PRIuz
1897 ", respond with STATUS_BUFFER_TOO_SMALL",
1898 operation->outputBufferLength, outputBufferLength);
1900 *pIoStatus = STATUS_BUFFER_TOO_SMALL;
1901 result = *pIoStatus;
1902 outputBufferLength = 0;
1903 objectBufferLength = 0;
1907 Stream_Write_UINT32(out, (UINT32)outputBufferLength);
1908 smartcard_pack_common_type_header(out);
1909 smartcard_pack_private_type_header(
1910 out, (UINT32)objectBufferLength);
1911 Stream_Write_INT32(out, result);
1912 if (!Stream_SetPosition(out, Stream_Length(out)))
1913 return SCARD_E_BAD_SEEK;
1914 return SCARD_S_SUCCESS;
1917void context_free(
void* arg)
1919 struct s_scard_context_element* element = arg;
1923 if (element->fn_free)
1924 element->fn_free(element->context);
1928#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
1929scard_call_context* smartcard_call_context_new(
const rdpSettings* settings)
1932 if (!inst || !inst->context)
1934 return smartcard_call_context_new_with_context(inst->context);
1938scard_call_context* smartcard_call_context_new_with_context(rdpContext* context)
1940 WINPR_ASSERT(context);
1941 scard_call_context* ctx = calloc(1,
sizeof(scard_call_context));
1945 ctx->context = context;
1947 const rdpSettings* settings = context->settings;
1948 WINPR_ASSERT(settings);
1950 ctx->log = WLog_Get(SCARD_TAG);
1951 WINPR_ASSERT(ctx->log);
1953 ctx->stopEvent = CreateEventA(
nullptr, TRUE, FALSE,
nullptr);
1954 if (!ctx->stopEvent)
1957 ctx->names = LinkedList_New();
1961#if defined(WITH_SMARTCARD_EMULATE)
1965 if (ctx->useEmulatedCard)
1967#if defined(WITH_SMARTCARD_EMULATE)
1968 ctx->emulation = Emulate_New(settings);
1969 if (!ctx->emulation)
1972 WLog_Print(ctx->log, WLOG_ERROR,
"Smartcard emulation requested, but not supported!");
1981 ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
1983 if (!ctx->hWinSCardLibrary)
1985 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard library: '%s'",
1990 if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
1992 ctx->pWinSCardApi = &ctx->WinSCardApi;
1996 ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
1999 if (!ctx->pWinSCardApi)
2001 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard API!");
2006 ctx->rgSCardContextList = HashTable_New(FALSE);
2007 if (!ctx->rgSCardContextList)
2011 wObject* obj = HashTable_ValueObject(ctx->rgSCardContextList);
2018 WINPR_PRAGMA_DIAG_PUSH
2019 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2020 smartcard_call_context_free(ctx);
2021 WINPR_PRAGMA_DIAG_POP
2025void smartcard_call_context_free(scard_call_context* ctx)
2030 smartcard_call_context_signal_stop(ctx, FALSE);
2032 LinkedList_Free(ctx->names);
2033 if (ctx->StartedEvent)
2035 WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
2036 wrap_raw(ctx, SCardReleaseStartedEvent);
2039 if (ctx->useEmulatedCard)
2041#ifdef WITH_SMARTCARD_EMULATE
2044 Emulate_Free(ctx->emulation);
2045 ctx->emulation =
nullptr;
2050 if (ctx->hWinSCardLibrary)
2053 FreeLibrary(ctx->hWinSCardLibrary);
2054 ctx->hWinSCardLibrary =
nullptr;
2057 ctx->pWinSCardApi =
nullptr;
2059 HashTable_Free(ctx->rgSCardContextList);
2060 (void)CloseHandle(ctx->stopEvent);
2064BOOL smartcard_call_context_add(scard_call_context* ctx,
const char* name)
2068 return LinkedList_AddLast(ctx->names, name);
2071BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2074 if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
2076 wrap(ctx, SCardCancel, hContext);
2081BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2084 wrap(ctx, SCardReleaseContext, hContext);
2088BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
2093 HashTable_Clear(ctx->rgSCardContextList);
2097BOOL smarcard_call_set_callbacks(scard_call_context* ctx,
void* userdata,
2098 void* (*fn_new)(
void*, SCARDCONTEXT),
void (*fn_free)(
void*))
2101 ctx->userdata = userdata;
2102 ctx->fn_new = fn_new;
2103 ctx->fn_free = fn_free;
2107void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2109 struct s_scard_context_element* element =
nullptr;
2112 element = HashTable_GetItemValue(ctx->rgSCardContextList, (
void*)hContext);
2115 return element->context;
2118BOOL smartcard_call_is_configured(scard_call_context* ctx)
2122#if defined(WITH_SMARTCARD_EMULATE)
2123 if (ctx->useEmulatedCard)
2124 return Emulate_IsConfigured(ctx->emulation);
2130BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
2134 if (!ctx->stopEvent)
2138 return ResetEvent(ctx->stopEvent);
2140 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