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);
343 *mszReaders =
nullptr;
344 rc = filter_device_by_name_a(list, &readers, cchReaders);
346 *mszReaders = ConvertMszUtf8NToWCharAlloc(readers, rc,
nullptr);
354static LONG smartcard_ListReadersA_Call(scard_call_context* smartcard,
wStream* out,
358 LPSTR mszReaders =
nullptr;
360 WINPR_ASSERT(smartcard);
362 WINPR_ASSERT(operation);
365 DWORD cchReaders = SCARD_AUTOALLOCATE;
366 LONG status = ret.ReturnCode = wrap(smartcard, SCardListReadersA, operation->hContext,
367 (LPCSTR)call->mszGroups, (LPSTR)&mszReaders, &cchReaders);
368 if (status == SCARD_S_SUCCESS)
370 if (cchReaders == SCARD_AUTOALLOCATE)
371 status = SCARD_F_UNKNOWN_ERROR;
374 if (status != SCARD_S_SUCCESS)
376 (void)scard_log_status_error_wlog(smartcard->log,
"SCardListReadersA", status);
377 return smartcard_pack_list_readers_return(out, &ret, FALSE);
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, mszReaders);
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 cchReaders = filter_device_by_name_w(smartcard->names, &mszReaders.pw, cchReaders);
438 ret.msz = mszReaders.pb;
439 ret.cBytes = cchReaders *
sizeof(WCHAR);
440 status = smartcard_pack_list_readers_return(out, &ret, TRUE);
443 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaders.pb);
445 if (status != SCARD_S_SUCCESS)
448 return ret.ReturnCode;
451static LONG smartcard_IntroduceReaderGroupA_Call(scard_call_context* smartcard,
452 WINPR_ATTR_UNUSED
wStream* out,
458 WINPR_ASSERT(smartcard);
460 WINPR_ASSERT(operation);
462 call = &operation->call.contextAndStringA;
463 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupA, operation->hContext, call->sz);
464 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderGroupA", ret.ReturnCode);
465 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderGroupA");
466 return ret.ReturnCode;
469static LONG smartcard_IntroduceReaderGroupW_Call(scard_call_context* smartcard,
470 WINPR_ATTR_UNUSED
wStream* out,
476 WINPR_ASSERT(smartcard);
478 WINPR_ASSERT(operation);
480 call = &operation->call.contextAndStringW;
481 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupW, operation->hContext, call->sz);
482 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderGroupW", ret.ReturnCode);
483 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderGroupW");
484 return ret.ReturnCode;
487static LONG smartcard_IntroduceReaderA_Call(scard_call_context* smartcard,
488 WINPR_ATTR_UNUSED
wStream* out,
494 WINPR_ASSERT(smartcard);
496 WINPR_ASSERT(operation);
498 call = &operation->call.contextAndTwoStringA;
500 wrap(smartcard, SCardIntroduceReaderA, operation->hContext, call->sz1, call->sz2);
501 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderA", ret.ReturnCode);
502 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderA");
503 return ret.ReturnCode;
506static LONG smartcard_IntroduceReaderW_Call(scard_call_context* smartcard,
507 WINPR_ATTR_UNUSED
wStream* out,
513 WINPR_ASSERT(smartcard);
515 WINPR_ASSERT(operation);
517 call = &operation->call.contextAndTwoStringW;
519 wrap(smartcard, SCardIntroduceReaderW, operation->hContext, call->sz1, call->sz2);
520 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderW", ret.ReturnCode);
521 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderW");
522 return ret.ReturnCode;
525static LONG smartcard_ForgetReaderA_Call(scard_call_context* smartcard,
526 WINPR_ATTR_UNUSED
wStream* out,
532 WINPR_ASSERT(smartcard);
534 WINPR_ASSERT(operation);
536 call = &operation->call.contextAndStringA;
537 ret.ReturnCode = wrap(smartcard, SCardForgetReaderA, operation->hContext, call->sz);
538 scard_log_status_error_wlog(smartcard->log,
"SCardForgetReaderA", ret.ReturnCode);
539 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardForgetReaderA");
540 return ret.ReturnCode;
543static LONG smartcard_ForgetReaderW_Call(scard_call_context* smartcard,
544 WINPR_ATTR_UNUSED
wStream* out,
550 WINPR_ASSERT(smartcard);
552 WINPR_ASSERT(operation);
554 call = &operation->call.contextAndStringW;
555 ret.ReturnCode = wrap(smartcard, SCardForgetReaderW, operation->hContext, call->sz);
556 scard_log_status_error_wlog(smartcard->log,
"SCardForgetReaderW", ret.ReturnCode);
557 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardForgetReaderW");
558 return ret.ReturnCode;
561static LONG smartcard_AddReaderToGroupA_Call(scard_call_context* smartcard,
562 WINPR_ATTR_UNUSED
wStream* out,
568 WINPR_ASSERT(smartcard);
570 WINPR_ASSERT(operation);
572 call = &operation->call.contextAndTwoStringA;
574 wrap(smartcard, SCardAddReaderToGroupA, operation->hContext, call->sz1, call->sz2);
575 scard_log_status_error_wlog(smartcard->log,
"SCardAddReaderToGroupA", ret.ReturnCode);
576 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardAddReaderToGroupA");
577 return ret.ReturnCode;
580static LONG smartcard_AddReaderToGroupW_Call(scard_call_context* smartcard,
581 WINPR_ATTR_UNUSED
wStream* out,
587 WINPR_ASSERT(smartcard);
589 WINPR_ASSERT(operation);
591 call = &operation->call.contextAndTwoStringW;
593 wrap(smartcard, SCardAddReaderToGroupW, operation->hContext, call->sz1, call->sz2);
594 scard_log_status_error_wlog(smartcard->log,
"SCardAddReaderToGroupW", ret.ReturnCode);
595 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardAddReaderToGroupA");
596 return ret.ReturnCode;
599static LONG smartcard_RemoveReaderFromGroupA_Call(scard_call_context* smartcard,
600 WINPR_ATTR_UNUSED
wStream* out,
606 WINPR_ASSERT(smartcard);
608 WINPR_ASSERT(operation);
610 call = &operation->call.contextAndTwoStringA;
612 wrap(smartcard, SCardRemoveReaderFromGroupA, operation->hContext, call->sz1, call->sz2);
613 scard_log_status_error_wlog(smartcard->log,
"SCardRemoveReaderFromGroupA", ret.ReturnCode);
614 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardRemoveReaderFromGroupA");
615 return ret.ReturnCode;
618static LONG smartcard_RemoveReaderFromGroupW_Call(scard_call_context* smartcard,
619 WINPR_ATTR_UNUSED
wStream* out,
625 WINPR_ASSERT(smartcard);
627 WINPR_ASSERT(operation);
629 call = &operation->call.contextAndTwoStringW;
631 wrap(smartcard, SCardRemoveReaderFromGroupW, operation->hContext, call->sz1, call->sz2);
632 scard_log_status_error_wlog(smartcard->log,
"SCardRemoveReaderFromGroupW", ret.ReturnCode);
633 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardRemoveReaderFromGroupW");
634 return ret.ReturnCode;
637static LONG smartcard_LocateCardsA_Call(scard_call_context* smartcard,
wStream* out,
644 WINPR_ASSERT(smartcard);
645 WINPR_ASSERT(operation);
647 call = &operation->call.locateCardsA;
649 ret.ReturnCode = wrap(smartcard, SCardLocateCardsA, operation->hContext, call->mszCards,
650 call->rgReaderStates, call->cReaders);
651 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsA", ret.ReturnCode);
652 ret.cReaders = call->cReaders;
653 ret.rgReaderStates =
nullptr;
655 if (ret.cReaders > 0)
659 if (!ret.rgReaderStates)
660 return STATUS_NO_MEMORY;
663 for (UINT32 x = 0; x < ret.cReaders; x++)
665 ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
666 ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
667 ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
668 CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
669 sizeof(ret.rgReaderStates[x].rgbAtr));
672 status = smartcard_pack_locate_cards_return(out, &ret);
674 if (status != SCARD_S_SUCCESS)
677 return ret.ReturnCode;
680static LONG smartcard_LocateCardsW_Call(scard_call_context* smartcard,
wStream* out,
687 WINPR_ASSERT(smartcard);
688 WINPR_ASSERT(operation);
690 call = &operation->call.locateCardsW;
692 ret.ReturnCode = wrap(smartcard, SCardLocateCardsW, operation->hContext, call->mszCards,
693 call->rgReaderStates, call->cReaders);
694 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsW", ret.ReturnCode);
695 ret.cReaders = call->cReaders;
696 ret.rgReaderStates =
nullptr;
698 if (ret.cReaders > 0)
702 if (!ret.rgReaderStates)
703 return STATUS_NO_MEMORY;
706 for (UINT32 x = 0; x < ret.cReaders; x++)
708 ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
709 ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
710 ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
711 CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
712 sizeof(ret.rgReaderStates[x].rgbAtr));
715 status = smartcard_pack_locate_cards_return(out, &ret);
717 if (status != SCARD_S_SUCCESS)
720 return ret.ReturnCode;
723static LONG smartcard_ReadCacheA_Call(scard_call_context* smartcard,
wStream* out,
731 WINPR_ASSERT(smartcard);
733 WINPR_ASSERT(operation);
735 call = &operation->call.readCacheA;
736 autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE);
738 if (!call->Common.fPbDataIsNULL)
740 ret.cbDataLen = call->Common.cbDataLen;
743 ret.pbData = malloc(ret.cbDataLen);
745 return SCARD_F_INTERNAL_ERROR;
750 ret.ReturnCode = wrap(smartcard, SCardReadCacheA, operation->hContext,
751 call->Common.CardIdentifier, call->Common.FreshnessCounter,
752 call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
755 wrap(smartcard, SCardReadCacheA, operation->hContext, call->Common.CardIdentifier,
756 call->Common.FreshnessCounter, call->szLookupName, ret.pbData, &ret.cbDataLen);
757 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
758 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
760 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheA", ret.ReturnCode);
763 status = smartcard_pack_read_cache_return(out, &ret);
765 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
768 if (status != SCARD_S_SUCCESS)
771 return ret.ReturnCode;
774static LONG smartcard_ReadCacheW_Call(scard_call_context* smartcard,
wStream* out,
781 WINPR_ASSERT(smartcard);
783 WINPR_ASSERT(operation);
785 call = &operation->call.readCacheW;
787 if (!call->Common.fPbDataIsNULL)
788 ret.cbDataLen = SCARD_AUTOALLOCATE;
791 wrap(smartcard, SCardReadCacheW, operation->hContext, call->Common.CardIdentifier,
792 call->Common.FreshnessCounter, call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
794 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
795 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
797 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheW", ret.ReturnCode);
800 status = smartcard_pack_read_cache_return(out, &ret);
802 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
804 if (status != SCARD_S_SUCCESS)
807 return ret.ReturnCode;
810static LONG smartcard_WriteCacheA_Call(scard_call_context* smartcard,
811 WINPR_ATTR_UNUSED
wStream* out,
817 WINPR_ASSERT(smartcard);
819 WINPR_ASSERT(operation);
821 call = &operation->call.writeCacheA;
823 ret.ReturnCode = wrap(smartcard, SCardWriteCacheA, operation->hContext,
824 call->Common.CardIdentifier, call->Common.FreshnessCounter,
825 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
826 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheA", ret.ReturnCode);
827 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheA");
828 return ret.ReturnCode;
831static LONG smartcard_WriteCacheW_Call(scard_call_context* smartcard,
832 WINPR_ATTR_UNUSED
wStream* out,
838 WINPR_ASSERT(smartcard);
840 WINPR_ASSERT(operation);
842 call = &operation->call.writeCacheW;
844 ret.ReturnCode = wrap(smartcard, SCardWriteCacheW, operation->hContext,
845 call->Common.CardIdentifier, call->Common.FreshnessCounter,
846 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
847 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheW", ret.ReturnCode);
848 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheW");
849 return ret.ReturnCode;
852static LONG smartcard_GetTransmitCount_Call(scard_call_context* smartcard,
wStream* out,
858 WINPR_ASSERT(smartcard);
860 WINPR_ASSERT(operation);
862 ret.ReturnCode = wrap(smartcard, SCardGetTransmitCount, operation->hCard, &ret.cTransmitCount);
863 scard_log_status_error_wlog(smartcard->log,
"SCardGetTransmitCount", ret.ReturnCode);
864 status = smartcard_pack_get_transmit_count_return(out, &ret);
865 if (status != SCARD_S_SUCCESS)
868 return ret.ReturnCode;
871static LONG smartcard_ReleaseStartedEvent_Call(scard_call_context* smartcard,
wStream* out,
874 WINPR_UNUSED(smartcard);
876 WINPR_UNUSED(operation);
878 WLog_Print(smartcard->log, WLOG_WARN,
879 "According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
880 "this is not supported?!?");
881 return SCARD_E_UNSUPPORTED_FEATURE;
884static LONG smartcard_GetReaderIcon_Call(scard_call_context* smartcard,
wStream* out,
891 WINPR_ASSERT(smartcard);
893 WINPR_ASSERT(operation);
895 call = &operation->call.getReaderIcon;
897 ret.cbDataLen = SCARD_AUTOALLOCATE;
898 ret.ReturnCode = wrap(smartcard, SCardGetReaderIconW, operation->hContext, call->szReaderName,
899 (LPBYTE)&ret.pbData, &ret.cbDataLen);
900 scard_log_status_error_wlog(smartcard->log,
"SCardGetReaderIconW", ret.ReturnCode);
901 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cbDataLen == SCARD_AUTOALLOCATE))
902 return SCARD_F_UNKNOWN_ERROR;
904 status = smartcard_pack_get_reader_icon_return(out, &ret);
905 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
906 if (status != SCARD_S_SUCCESS)
909 return ret.ReturnCode;
912static LONG smartcard_GetDeviceTypeId_Call(scard_call_context* smartcard,
wStream* out,
919 WINPR_ASSERT(smartcard);
921 WINPR_ASSERT(operation);
923 call = &operation->call.getDeviceTypeId;
925 ret.ReturnCode = wrap(smartcard, SCardGetDeviceTypeIdW, operation->hContext, call->szReaderName,
927 scard_log_status_error_wlog(smartcard->log,
"SCardGetDeviceTypeIdW", ret.ReturnCode);
929 status = smartcard_pack_device_type_id_return(out, &ret);
930 if (status != SCARD_S_SUCCESS)
933 return ret.ReturnCode;
936static BOOL smartcard_context_was_aborted(scard_call_context* smartcard)
938 WINPR_ASSERT(smartcard);
940 HANDLE handles[] = { smartcard->stopEvent, freerdp_abort_event(smartcard->context) };
941 const DWORD rc = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, 0);
942 if ((rc >= WAIT_OBJECT_0) && (rc <= WAIT_OBJECT_0 + ARRAYSIZE(handles)))
947static LONG smartcard_GetStatusChangeA_Call(scard_call_context* smartcard,
wStream* out,
950 LONG status = STATUS_NO_MEMORY;
952 const DWORD dwTimeStep = 100;
957 WINPR_ASSERT(smartcard);
959 WINPR_ASSERT(operation);
961 call = &operation->call.getStatusChangeA;
962 dwTimeOut = call->dwTimeOut;
964 if (call->cReaders > 0)
966 ret.cReaders = call->cReaders;
969 if (!rgReaderStates || !ret.rgReaderStates)
973 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
975 if (call->cReaders > 0)
976 memcpy(rgReaderStates, call->rgReaderStates,
978 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
979 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
980 if (ret.ReturnCode != SCARD_E_TIMEOUT)
982 if (smartcard_context_was_aborted(smartcard))
984 if (dwTimeOut != INFINITE)
987 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", ret.ReturnCode);
989 for (UINT32 index = 0; index < ret.cReaders; index++)
994 rout->dwCurrentState = cur->dwCurrentState;
995 rout->dwEventState = cur->dwEventState;
996 rout->cbAtr = cur->cbAtr;
997 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1000 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1002 free(ret.rgReaderStates);
1003 free(rgReaderStates);
1004 if (status != SCARD_S_SUCCESS)
1006 return ret.ReturnCode;
1009static LONG smartcard_GetStatusChangeW_Call(scard_call_context* smartcard,
wStream* out,
1012 LONG status = STATUS_NO_MEMORY;
1013 DWORD dwTimeOut = 0;
1014 const DWORD dwTimeStep = 100;
1018 WINPR_ASSERT(smartcard);
1020 WINPR_ASSERT(operation);
1023 dwTimeOut = call->dwTimeOut;
1025 if (call->cReaders > 0)
1027 ret.cReaders = call->cReaders;
1030 if (!rgReaderStates || !ret.rgReaderStates)
1034 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
1036 if (call->cReaders > 0)
1037 memcpy(rgReaderStates, call->rgReaderStates,
1040 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
1041 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
1043 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1045 if (smartcard_context_was_aborted(smartcard))
1047 if (dwTimeOut != INFINITE)
1050 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeW", ret.ReturnCode);
1052 for (UINT32 index = 0; index < ret.cReaders; index++)
1057 rout->dwCurrentState = cur->dwCurrentState;
1058 rout->dwEventState = cur->dwEventState;
1059 rout->cbAtr = cur->cbAtr;
1060 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1063 status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
1065 free(ret.rgReaderStates);
1066 free(rgReaderStates);
1067 if (status != SCARD_S_SUCCESS)
1069 return ret.ReturnCode;
1072static LONG smartcard_Cancel_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1077 WINPR_ASSERT(smartcard);
1079 WINPR_ASSERT(operation);
1081 ret.ReturnCode = wrap(smartcard, SCardCancel, operation->hContext);
1082 scard_log_status_error_wlog(smartcard->log,
"SCardCancel", ret.ReturnCode);
1083 smartcard_trace_long_return_int(smartcard->log, &ret,
"Cancel");
1084 return ret.ReturnCode;
1087static LONG smartcard_ConnectA_Call(scard_call_context* smartcard,
wStream* out,
1091 SCARDHANDLE hCard = 0;
1095 WINPR_ASSERT(smartcard);
1097 WINPR_ASSERT(operation);
1099 call = &operation->call.connectA;
1101 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1102 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1104 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1107 ret.ReturnCode = wrap(smartcard, SCardConnectA, operation->hContext, (
char*)call->szReader,
1108 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1109 &ret.dwActiveProtocol);
1110 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1111 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1113 status = smartcard_pack_connect_return(out, &ret);
1114 if (status != SCARD_S_SUCCESS)
1117 status = ret.ReturnCode;
1123static LONG smartcard_ConnectW_Call(scard_call_context* smartcard,
wStream* out,
1127 SCARDHANDLE hCard = 0;
1131 WINPR_ASSERT(smartcard);
1133 WINPR_ASSERT(operation);
1135 call = &operation->call.connectW;
1137 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1138 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1140 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1143 ret.ReturnCode = wrap(smartcard, SCardConnectW, operation->hContext, (WCHAR*)call->szReader,
1144 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1145 &ret.dwActiveProtocol);
1146 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1147 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1149 status = smartcard_pack_connect_return(out, &ret);
1150 if (status != SCARD_S_SUCCESS)
1153 status = ret.ReturnCode;
1159static LONG smartcard_Reconnect_Call(scard_call_context* smartcard,
wStream* out,
1166 WINPR_ASSERT(smartcard);
1168 WINPR_ASSERT(operation);
1170 call = &operation->call.reconnect;
1172 wrap(smartcard, SCardReconnect, operation->hCard, call->dwShareMode,
1173 call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
1174 scard_log_status_error_wlog(smartcard->log,
"SCardReconnect", ret.ReturnCode);
1175 status = smartcard_pack_reconnect_return(out, &ret);
1176 if (status != SCARD_S_SUCCESS)
1179 return ret.ReturnCode;
1182static LONG smartcard_Disconnect_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1188 WINPR_ASSERT(smartcard);
1190 WINPR_ASSERT(operation);
1192 call = &operation->call.hCardAndDisposition;
1194 ret.ReturnCode = wrap(smartcard, SCardDisconnect, operation->hCard, call->dwDisposition);
1195 scard_log_status_error_wlog(smartcard->log,
"SCardDisconnect", ret.ReturnCode);
1196 smartcard_trace_long_return_int(smartcard->log, &ret,
"Disconnect");
1198 return ret.ReturnCode;
1201static LONG smartcard_BeginTransaction_Call(scard_call_context* smartcard,
1202 WINPR_ATTR_UNUSED
wStream* out,
1207 WINPR_ASSERT(smartcard);
1209 WINPR_ASSERT(operation);
1211 ret.ReturnCode = wrap(smartcard, SCardBeginTransaction, operation->hCard);
1212 scard_log_status_error_wlog(smartcard->log,
"SCardBeginTransaction", ret.ReturnCode);
1213 smartcard_trace_long_return_int(smartcard->log, &ret,
"BeginTransaction");
1214 return ret.ReturnCode;
1217static LONG smartcard_EndTransaction_Call(scard_call_context* smartcard,
1218 WINPR_ATTR_UNUSED
wStream* out,
1224 WINPR_ASSERT(smartcard);
1226 WINPR_ASSERT(operation);
1228 call = &operation->call.hCardAndDisposition;
1230 ret.ReturnCode = wrap(smartcard, SCardEndTransaction, operation->hCard, call->dwDisposition);
1231 scard_log_status_error_wlog(smartcard->log,
"SCardEndTransaction", ret.ReturnCode);
1232 smartcard_trace_long_return_int(smartcard->log, &ret,
"EndTransaction");
1233 return ret.ReturnCode;
1236static LONG smartcard_State_Call(scard_call_context* smartcard,
wStream* out,
1242 WINPR_ASSERT(smartcard);
1244 WINPR_ASSERT(operation);
1246 ret.cbAtrLen = SCARD_ATR_LENGTH;
1247 ret.ReturnCode = wrap(smartcard, SCardState, operation->hCard, &ret.dwState, &ret.dwProtocol,
1248 (BYTE*)&ret.rgAtr, &ret.cbAtrLen);
1250 scard_log_status_error_wlog(smartcard->log,
"SCardState", ret.ReturnCode);
1251 status = smartcard_pack_state_return(out, &ret);
1252 if (status != SCARD_S_SUCCESS)
1255 return ret.ReturnCode;
1258static LONG smartcard_StatusA_Call(scard_call_context* smartcard,
wStream* out,
1263 DWORD cchReaderLen = 0;
1265 LPSTR mszReaderNames =
nullptr;
1268 WINPR_ASSERT(smartcard);
1270 WINPR_ASSERT(operation);
1272 call = &operation->call.status;
1274 call->cbAtrLen = 32;
1275 cbAtrLen = call->cbAtrLen;
1277 if (call->fmszReaderNamesIsNULL)
1280 cchReaderLen = SCARD_AUTOALLOCATE;
1282 status = ret.ReturnCode =
1283 wrap(smartcard, SCardStatusA, operation->hCard,
1284 call->fmszReaderNamesIsNULL ?
nullptr : (LPSTR)&mszReaderNames, &cchReaderLen,
1285 &ret.dwState, &ret.dwProtocol, cbAtrLen ? (BYTE*)&ret.pbAtr : nullptr, &cbAtrLen);
1287 scard_log_status_error_wlog(smartcard->log,
"SCardStatusA", status);
1288 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchReaderLen == SCARD_AUTOALLOCATE))
1289 return SCARD_F_UNKNOWN_ERROR;
1291 if (status == SCARD_S_SUCCESS)
1293 if (!call->fmszReaderNamesIsNULL)
1294 ret.mszReaderNames = (BYTE*)mszReaderNames;
1296 ret.cBytes = cchReaderLen;
1299 ret.cbAtrLen = cbAtrLen;
1302 status = smartcard_pack_status_return(out, &ret, FALSE);
1305 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1307 if (status != SCARD_S_SUCCESS)
1309 return ret.ReturnCode;
1312static LONG smartcard_StatusW_Call(scard_call_context* smartcard,
wStream* out,
1317 LPWSTR mszReaderNames =
nullptr;
1321 WINPR_ASSERT(smartcard);
1323 WINPR_ASSERT(operation);
1325 call = &operation->call.status;
1331 cbAtrLen = call->cbAtrLen = 32;
1333 if (call->fmszReaderNamesIsNULL)
1336 ret.cBytes = SCARD_AUTOALLOCATE;
1338 status = ret.ReturnCode =
1339 wrap(smartcard, SCardStatusW, operation->hCard,
1340 call->fmszReaderNamesIsNULL ?
nullptr : (LPWSTR)&mszReaderNames, &ret.cBytes,
1341 &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
1342 scard_log_status_error_wlog(smartcard->log,
"SCardStatusW", status);
1343 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cBytes == SCARD_AUTOALLOCATE))
1344 return SCARD_F_UNKNOWN_ERROR;
1347 if (status == SCARD_S_SUCCESS)
1349 if (!call->fmszReaderNamesIsNULL)
1350 ret.mszReaderNames = (BYTE*)mszReaderNames;
1352 ret.cbAtrLen = cbAtrLen;
1355 if (ret.cBytes != SCARD_AUTOALLOCATE)
1358 WINPR_ASSERT(ret.cBytes < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
1359 blen =
sizeof(WCHAR) * ret.cBytes;
1360 WINPR_ASSERT(blen <= UINT32_MAX);
1361 ret.cBytes = (UINT32)blen;
1364 status = smartcard_pack_status_return(out, &ret, TRUE);
1365 if (status != SCARD_S_SUCCESS)
1369 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1371 return ret.ReturnCode;
1374static LONG smartcard_Transmit_Call(scard_call_context* smartcard,
wStream* out,
1381 WINPR_ASSERT(smartcard);
1383 WINPR_ASSERT(operation);
1385 call = &operation->call.transmit;
1386 ret.cbRecvLength = 0;
1387 ret.pbRecvBuffer =
nullptr;
1389 if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
1391 if (call->cbRecvLength >= 66560)
1392 call->cbRecvLength = 66560;
1394 ret.cbRecvLength = call->cbRecvLength;
1395 ret.pbRecvBuffer = (BYTE*)malloc(ret.cbRecvLength);
1397 if (!ret.pbRecvBuffer)
1398 return STATUS_NO_MEMORY;
1401 ret.pioRecvPci = call->pioRecvPci;
1403 wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
1404 call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
1406 scard_log_status_error_wlog(smartcard->log,
"SCardTransmit", ret.ReturnCode);
1408 status = smartcard_pack_transmit_return(out, &ret);
1409 free(ret.pbRecvBuffer);
1411 if (status != SCARD_S_SUCCESS)
1413 return ret.ReturnCode;
1416static LONG smartcard_Control_Call(scard_call_context* smartcard,
wStream* out,
1423 WINPR_ASSERT(smartcard);
1425 WINPR_ASSERT(operation);
1427 call = &operation->call.control;
1428 ret.cbOutBufferSize = call->cbOutBufferSize;
1429 ret.pvOutBuffer = (BYTE*)malloc(call->cbOutBufferSize);
1431 if (!ret.pvOutBuffer)
1432 return SCARD_E_NO_MEMORY;
1435 wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
1436 call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
1437 scard_log_status_error_wlog(smartcard->log,
"SCardControl", ret.ReturnCode);
1438 status = smartcard_pack_control_return(out, &ret);
1440 free(ret.pvOutBuffer);
1441 if (status != SCARD_S_SUCCESS)
1443 return ret.ReturnCode;
1446static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard,
wStream* out,
1449 BOOL autoAllocate = FALSE;
1451 DWORD cbAttrLen = 0;
1452 LPBYTE pbAttr =
nullptr;
1456 WINPR_ASSERT(smartcard);
1457 WINPR_ASSERT(operation);
1459 call = &operation->call.getAttrib;
1461 if (!call->fpbAttrIsNULL)
1463 autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE);
1464 cbAttrLen = call->cbAttrLen;
1465 if (cbAttrLen && !autoAllocate)
1467 ret.pbAttr = (BYTE*)malloc(cbAttrLen);
1470 return SCARD_E_NO_MEMORY;
1473 pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
1477 wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
1478 scard_log_status_error_wlog(smartcard->log,
"SCardGetAttrib", ret.ReturnCode);
1479 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cbAttrLen == SCARD_AUTOALLOCATE))
1480 return SCARD_F_UNKNOWN_ERROR;
1482 ret.cbAttrLen = cbAttrLen;
1484 status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
1487 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
1493static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1499 WINPR_ASSERT(smartcard);
1501 WINPR_ASSERT(operation);
1503 call = &operation->call.setAttrib;
1505 ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
1507 scard_log_status_error_wlog(smartcard->log,
"SCardSetAttrib", ret.ReturnCode);
1508 smartcard_trace_long_return_int(smartcard->log, &ret,
"SetAttrib");
1510 return ret.ReturnCode;
1513static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard,
1514 WINPR_ATTR_UNUSED
wStream* out,
1517 LONG status = SCARD_S_SUCCESS;
1519 WINPR_ASSERT(smartcard);
1521 WINPR_UNUSED(operation);
1523 if (!smartcard->StartedEvent)
1524 smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
1526 if (!smartcard->StartedEvent)
1527 status = SCARD_E_NO_SERVICE;
1532static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard,
wStream* out,
1540 WINPR_ASSERT(smartcard);
1541 WINPR_ASSERT(operation);
1543 call = &operation->call.locateCardsByATRA;
1547 return STATUS_NO_MEMORY;
1549 for (UINT32 i = 0; i < call->cReaders; i++)
1552 state->szReader = call->rgReaderStates[i].szReader;
1553 state->dwCurrentState = call->rgReaderStates[i].dwCurrentState;
1554 state->dwEventState = call->rgReaderStates[i].dwEventState;
1555 state->cbAtr = call->rgReaderStates[i].cbAtr;
1556 CopyMemory(&(state->rgbAtr), &(call->rgReaderStates[i].rgbAtr), 36);
1559 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1560 0x000001F4, states, call->cReaders);
1562 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", status);
1563 for (UINT32 i = 0; i < call->cAtrs; i++)
1565 for (UINT32 j = 0; j < call->cReaders; j++)
1567 for (UINT32 k = 0; k < call->rgAtrMasks[i].cbAtr; k++)
1569 if ((call->rgAtrMasks[i].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]) !=
1570 (states[j].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]))
1575 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1580 ret.cReaders = call->cReaders;
1581 ret.rgReaderStates =
nullptr;
1583 if (ret.cReaders > 0)
1586 if (!ret.rgReaderStates)
1589 return STATUS_NO_MEMORY;
1592 for (UINT32 i = 0; i < ret.cReaders; i++)
1595 ret.rgReaderStates[i].dwCurrentState = state->dwCurrentState;
1596 ret.rgReaderStates[i].dwEventState = state->dwEventState;
1597 ret.rgReaderStates[i].cbAtr = state->cbAtr;
1598 CopyMemory(&(ret.rgReaderStates[i].rgbAtr), &(state->rgbAtr),
1599 sizeof(ret.rgReaderStates[i].rgbAtr));
1604 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1606 free(ret.rgReaderStates);
1607 if (status != SCARD_S_SUCCESS)
1609 return ret.ReturnCode;
1612LONG smartcard_irp_device_control_call(scard_call_context* ctx,
wStream* out, NTSTATUS* pIoStatus,
1617 size_t objectBufferLength = 0;
1621 WINPR_ASSERT(pIoStatus);
1622 WINPR_ASSERT(operation);
1624 const UINT32 ioControlCode = operation->ioControlCode;
1632 const size_t outMaxLen = MAX(2048, operation->outputBufferLength);
1633 if (!Stream_EnsureRemainingCapacity(out, outMaxLen))
1634 return SCARD_E_NO_MEMORY;
1637 Stream_Write_UINT32(out, 0);
1638 Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH);
1639 Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH);
1640 Stream_Write_UINT32(out, 0);
1643 switch (ioControlCode)
1645 case SCARD_IOCTL_ESTABLISHCONTEXT:
1646 result = smartcard_EstablishContext_Call(ctx, out, operation);
1649 case SCARD_IOCTL_RELEASECONTEXT:
1650 result = smartcard_ReleaseContext_Call(ctx, out, operation);
1653 case SCARD_IOCTL_ISVALIDCONTEXT:
1654 result = smartcard_IsValidContext_Call(ctx, out, operation);
1657 case SCARD_IOCTL_LISTREADERGROUPSA:
1658 result = smartcard_ListReaderGroupsA_Call(ctx, out, operation);
1661 case SCARD_IOCTL_LISTREADERGROUPSW:
1662 result = smartcard_ListReaderGroupsW_Call(ctx, out, operation);
1665 case SCARD_IOCTL_LISTREADERSA:
1666 result = smartcard_ListReadersA_Call(ctx, out, operation);
1669 case SCARD_IOCTL_LISTREADERSW:
1670 result = smartcard_ListReadersW_Call(ctx, out, operation);
1673 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1674 result = smartcard_IntroduceReaderGroupA_Call(ctx, out, operation);
1677 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1678 result = smartcard_IntroduceReaderGroupW_Call(ctx, out, operation);
1681 case SCARD_IOCTL_FORGETREADERGROUPA:
1682 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
1685 case SCARD_IOCTL_FORGETREADERGROUPW:
1686 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
1689 case SCARD_IOCTL_INTRODUCEREADERA:
1690 result = smartcard_IntroduceReaderA_Call(ctx, out, operation);
1693 case SCARD_IOCTL_INTRODUCEREADERW:
1694 result = smartcard_IntroduceReaderW_Call(ctx, out, operation);
1697 case SCARD_IOCTL_FORGETREADERA:
1698 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
1701 case SCARD_IOCTL_FORGETREADERW:
1702 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
1705 case SCARD_IOCTL_ADDREADERTOGROUPA:
1706 result = smartcard_AddReaderToGroupA_Call(ctx, out, operation);
1709 case SCARD_IOCTL_ADDREADERTOGROUPW:
1710 result = smartcard_AddReaderToGroupW_Call(ctx, out, operation);
1713 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1714 result = smartcard_RemoveReaderFromGroupA_Call(ctx, out, operation);
1717 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1718 result = smartcard_RemoveReaderFromGroupW_Call(ctx, out, operation);
1721 case SCARD_IOCTL_LOCATECARDSA:
1722 result = smartcard_LocateCardsA_Call(ctx, out, operation);
1725 case SCARD_IOCTL_LOCATECARDSW:
1726 result = smartcard_LocateCardsW_Call(ctx, out, operation);
1729 case SCARD_IOCTL_GETSTATUSCHANGEA:
1730 result = smartcard_GetStatusChangeA_Call(ctx, out, operation);
1733 case SCARD_IOCTL_GETSTATUSCHANGEW:
1734 result = smartcard_GetStatusChangeW_Call(ctx, out, operation);
1737 case SCARD_IOCTL_CANCEL:
1738 result = smartcard_Cancel_Call(ctx, out, operation);
1741 case SCARD_IOCTL_CONNECTA:
1742 result = smartcard_ConnectA_Call(ctx, out, operation);
1745 case SCARD_IOCTL_CONNECTW:
1746 result = smartcard_ConnectW_Call(ctx, out, operation);
1749 case SCARD_IOCTL_RECONNECT:
1750 result = smartcard_Reconnect_Call(ctx, out, operation);
1753 case SCARD_IOCTL_DISCONNECT:
1754 result = smartcard_Disconnect_Call(ctx, out, operation);
1757 case SCARD_IOCTL_BEGINTRANSACTION:
1758 result = smartcard_BeginTransaction_Call(ctx, out, operation);
1761 case SCARD_IOCTL_ENDTRANSACTION:
1762 result = smartcard_EndTransaction_Call(ctx, out, operation);
1765 case SCARD_IOCTL_STATE:
1766 result = smartcard_State_Call(ctx, out, operation);
1769 case SCARD_IOCTL_STATUSA:
1770 result = smartcard_StatusA_Call(ctx, out, operation);
1773 case SCARD_IOCTL_STATUSW:
1774 result = smartcard_StatusW_Call(ctx, out, operation);
1777 case SCARD_IOCTL_TRANSMIT:
1778 result = smartcard_Transmit_Call(ctx, out, operation);
1781 case SCARD_IOCTL_CONTROL:
1782 result = smartcard_Control_Call(ctx, out, operation);
1785 case SCARD_IOCTL_GETATTRIB:
1786 result = smartcard_GetAttrib_Call(ctx, out, operation);
1789 case SCARD_IOCTL_SETATTRIB:
1790 result = smartcard_SetAttrib_Call(ctx, out, operation);
1793 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
1794 result = smartcard_AccessStartedEvent_Call(ctx, out, operation);
1797 case SCARD_IOCTL_LOCATECARDSBYATRA:
1798 result = smartcard_LocateCardsByATRA_Call(ctx, out, operation);
1801 case SCARD_IOCTL_LOCATECARDSBYATRW:
1802 result = smartcard_LocateCardsW_Call(ctx, out, operation);
1805 case SCARD_IOCTL_READCACHEA:
1806 result = smartcard_ReadCacheA_Call(ctx, out, operation);
1809 case SCARD_IOCTL_READCACHEW:
1810 result = smartcard_ReadCacheW_Call(ctx, out, operation);
1813 case SCARD_IOCTL_WRITECACHEA:
1814 result = smartcard_WriteCacheA_Call(ctx, out, operation);
1817 case SCARD_IOCTL_WRITECACHEW:
1818 result = smartcard_WriteCacheW_Call(ctx, out, operation);
1821 case SCARD_IOCTL_GETTRANSMITCOUNT:
1822 result = smartcard_GetTransmitCount_Call(ctx, out, operation);
1825 case SCARD_IOCTL_RELEASETARTEDEVENT:
1826 result = smartcard_ReleaseStartedEvent_Call(ctx, out, operation);
1829 case SCARD_IOCTL_GETREADERICON:
1830 result = smartcard_GetReaderIcon_Call(ctx, out, operation);
1833 case SCARD_IOCTL_GETDEVICETYPEID:
1834 result = smartcard_GetDeviceTypeId_Call(ctx, out, operation);
1838 result = STATUS_UNSUCCESSFUL;
1848 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
1849 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
1851 offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
1852 const LONG rc = smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
1853 if (rc != SCARD_S_SUCCESS)
1857 if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
1858 (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
1859 (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
1861 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
1862 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
1865 *pIoStatus = STATUS_SUCCESS;
1867 if ((result & 0xC0000000L) == 0xC0000000L)
1870 *pIoStatus = result;
1872 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
1873 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
1876 Stream_SealLength(out);
1877 size_t outputBufferLength = Stream_Length(out);
1878 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1879 outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1880 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1881 objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
1882 WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
1883 WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
1884 if (!Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH))
1885 return SCARD_E_BAD_SEEK;
1894 if (outputBufferLength > operation->outputBufferLength)
1896 WLog_Print(ctx->log, WLOG_WARN,
1897 "IRP warn: expected outputBufferLength %" PRIu32
", but current limit %" PRIuz
1898 ", respond with STATUS_BUFFER_TOO_SMALL",
1899 operation->outputBufferLength, outputBufferLength);
1901 *pIoStatus = STATUS_BUFFER_TOO_SMALL;
1902 result = *pIoStatus;
1903 outputBufferLength = 0;
1904 objectBufferLength = 0;
1908 Stream_Write_UINT32(out, (UINT32)outputBufferLength);
1909 smartcard_pack_common_type_header(out);
1910 smartcard_pack_private_type_header(
1911 out, (UINT32)objectBufferLength);
1912 Stream_Write_INT32(out, result);
1913 if (!Stream_SetPosition(out, Stream_Length(out)))
1914 return SCARD_E_BAD_SEEK;
1915 return SCARD_S_SUCCESS;
1918void context_free(
void* arg)
1920 struct s_scard_context_element* element = arg;
1924 if (element->fn_free)
1925 element->fn_free(element->context);
1929#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
1930scard_call_context* smartcard_call_context_new(
const rdpSettings* settings)
1933 if (!inst || !inst->context)
1935 return smartcard_call_context_new_with_context(inst->context);
1939scard_call_context* smartcard_call_context_new_with_context(rdpContext* context)
1941 WINPR_ASSERT(context);
1942 scard_call_context* ctx = calloc(1,
sizeof(scard_call_context));
1946 ctx->context = context;
1948 const rdpSettings* settings = context->settings;
1949 WINPR_ASSERT(settings);
1951 ctx->log = WLog_Get(SCARD_TAG);
1952 WINPR_ASSERT(ctx->log);
1954 ctx->stopEvent = CreateEventA(
nullptr, TRUE, FALSE,
nullptr);
1955 if (!ctx->stopEvent)
1958 ctx->names = LinkedList_New();
1962#if defined(WITH_SMARTCARD_EMULATE)
1966 if (ctx->useEmulatedCard)
1968#if defined(WITH_SMARTCARD_EMULATE)
1969 ctx->emulation = Emulate_New(settings);
1970 if (!ctx->emulation)
1973 WLog_Print(ctx->log, WLOG_ERROR,
"Smartcard emulation requested, but not supported!");
1982 ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
1984 if (!ctx->hWinSCardLibrary)
1986 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard library: '%s'",
1991 if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
1993 ctx->pWinSCardApi = &ctx->WinSCardApi;
1997 ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
2000 if (!ctx->pWinSCardApi)
2002 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard API!");
2007 ctx->rgSCardContextList = HashTable_New(FALSE);
2008 if (!ctx->rgSCardContextList)
2012 wObject* obj = HashTable_ValueObject(ctx->rgSCardContextList);
2019 WINPR_PRAGMA_DIAG_PUSH
2020 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2021 smartcard_call_context_free(ctx);
2022 WINPR_PRAGMA_DIAG_POP
2026void smartcard_call_context_free(scard_call_context* ctx)
2031 smartcard_call_context_signal_stop(ctx, FALSE);
2033 LinkedList_Free(ctx->names);
2034 if (ctx->StartedEvent)
2036 WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
2037 wrap_raw(ctx, SCardReleaseStartedEvent);
2040 if (ctx->useEmulatedCard)
2042#ifdef WITH_SMARTCARD_EMULATE
2045 Emulate_Free(ctx->emulation);
2046 ctx->emulation =
nullptr;
2051 if (ctx->hWinSCardLibrary)
2054 FreeLibrary(ctx->hWinSCardLibrary);
2055 ctx->hWinSCardLibrary =
nullptr;
2058 ctx->pWinSCardApi =
nullptr;
2060 HashTable_Free(ctx->rgSCardContextList);
2061 (void)CloseHandle(ctx->stopEvent);
2065BOOL smartcard_call_context_add(scard_call_context* ctx,
const char* name)
2069 return LinkedList_AddLast(ctx->names, name);
2072BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2075 if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
2077 wrap(ctx, SCardCancel, hContext);
2082BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2085 wrap(ctx, SCardReleaseContext, hContext);
2089BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
2094 HashTable_Clear(ctx->rgSCardContextList);
2098BOOL smarcard_call_set_callbacks(scard_call_context* ctx,
void* userdata,
2099 void* (*fn_new)(
void*, SCARDCONTEXT),
void (*fn_free)(
void*))
2102 ctx->userdata = userdata;
2103 ctx->fn_new = fn_new;
2104 ctx->fn_free = fn_free;
2108void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2110 struct s_scard_context_element* element =
nullptr;
2113 element = HashTable_GetItemValue(ctx->rgSCardContextList, (
void*)hContext);
2116 return element->context;
2119BOOL smartcard_call_is_configured(scard_call_context* ctx)
2123#if defined(WITH_SMARTCARD_EMULATE)
2124 if (ctx->useEmulatedCard)
2125 return Emulate_IsConfigured(ctx->emulation);
2131BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
2135 if (!ctx->stopEvent)
2139 return ResetEvent(ctx->stopEvent);
2141 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