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*);
96struct s_scard_context_element
99 void (*fn_free)(
void*);
102static void context_free(
void* arg);
104static LONG smartcard_EstablishContext_Call(scard_call_context* smartcard,
wStream* out,
108 SCARDCONTEXT hContext = WINPR_C_ARRAY_INIT;
111 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 LONG smartcard_GetStatusChangeA_Call(scard_call_context* smartcard,
wStream* out,
939 LONG status = STATUS_NO_MEMORY;
941 const DWORD dwTimeStep = 100;
946 WINPR_ASSERT(smartcard);
948 WINPR_ASSERT(operation);
950 call = &operation->call.getStatusChangeA;
951 dwTimeOut = call->dwTimeOut;
953 if (call->cReaders > 0)
955 ret.cReaders = call->cReaders;
958 if (!rgReaderStates || !ret.rgReaderStates)
962 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
964 if (call->cReaders > 0)
965 memcpy(rgReaderStates, call->rgReaderStates,
967 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
968 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
969 if (ret.ReturnCode != SCARD_E_TIMEOUT)
971 if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
973 if (dwTimeOut != INFINITE)
976 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", ret.ReturnCode);
978 for (UINT32 index = 0; index < ret.cReaders; index++)
983 rout->dwCurrentState = cur->dwCurrentState;
984 rout->dwEventState = cur->dwEventState;
985 rout->cbAtr = cur->cbAtr;
986 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
989 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
991 free(ret.rgReaderStates);
992 free(rgReaderStates);
993 if (status != SCARD_S_SUCCESS)
995 return ret.ReturnCode;
998static LONG smartcard_GetStatusChangeW_Call(scard_call_context* smartcard,
wStream* out,
1001 LONG status = STATUS_NO_MEMORY;
1002 DWORD dwTimeOut = 0;
1003 const DWORD dwTimeStep = 100;
1007 WINPR_ASSERT(smartcard);
1009 WINPR_ASSERT(operation);
1012 dwTimeOut = call->dwTimeOut;
1014 if (call->cReaders > 0)
1016 ret.cReaders = call->cReaders;
1019 if (!rgReaderStates || !ret.rgReaderStates)
1023 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
1025 if (call->cReaders > 0)
1026 memcpy(rgReaderStates, call->rgReaderStates,
1029 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
1030 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
1032 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1034 if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
1036 if (dwTimeOut != INFINITE)
1039 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeW", ret.ReturnCode);
1041 for (UINT32 index = 0; index < ret.cReaders; index++)
1046 rout->dwCurrentState = cur->dwCurrentState;
1047 rout->dwEventState = cur->dwEventState;
1048 rout->cbAtr = cur->cbAtr;
1049 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1052 status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
1054 free(ret.rgReaderStates);
1055 free(rgReaderStates);
1056 if (status != SCARD_S_SUCCESS)
1058 return ret.ReturnCode;
1061static LONG smartcard_Cancel_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1066 WINPR_ASSERT(smartcard);
1068 WINPR_ASSERT(operation);
1070 ret.ReturnCode = wrap(smartcard, SCardCancel, operation->hContext);
1071 scard_log_status_error_wlog(smartcard->log,
"SCardCancel", ret.ReturnCode);
1072 smartcard_trace_long_return_int(smartcard->log, &ret,
"Cancel");
1073 return ret.ReturnCode;
1076static LONG smartcard_ConnectA_Call(scard_call_context* smartcard,
wStream* out,
1080 SCARDHANDLE hCard = 0;
1084 WINPR_ASSERT(smartcard);
1086 WINPR_ASSERT(operation);
1088 call = &operation->call.connectA;
1090 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1091 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1093 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1096 ret.ReturnCode = wrap(smartcard, SCardConnectA, operation->hContext, (
char*)call->szReader,
1097 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1098 &ret.dwActiveProtocol);
1099 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1100 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1102 status = smartcard_pack_connect_return(out, &ret);
1103 if (status != SCARD_S_SUCCESS)
1106 status = ret.ReturnCode;
1112static LONG smartcard_ConnectW_Call(scard_call_context* smartcard,
wStream* out,
1116 SCARDHANDLE hCard = 0;
1120 WINPR_ASSERT(smartcard);
1122 WINPR_ASSERT(operation);
1124 call = &operation->call.connectW;
1126 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1127 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1129 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1132 ret.ReturnCode = wrap(smartcard, SCardConnectW, operation->hContext, (WCHAR*)call->szReader,
1133 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1134 &ret.dwActiveProtocol);
1135 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1136 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1138 status = smartcard_pack_connect_return(out, &ret);
1139 if (status != SCARD_S_SUCCESS)
1142 status = ret.ReturnCode;
1148static LONG smartcard_Reconnect_Call(scard_call_context* smartcard,
wStream* out,
1155 WINPR_ASSERT(smartcard);
1157 WINPR_ASSERT(operation);
1159 call = &operation->call.reconnect;
1161 wrap(smartcard, SCardReconnect, operation->hCard, call->dwShareMode,
1162 call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
1163 scard_log_status_error_wlog(smartcard->log,
"SCardReconnect", ret.ReturnCode);
1164 status = smartcard_pack_reconnect_return(out, &ret);
1165 if (status != SCARD_S_SUCCESS)
1168 return ret.ReturnCode;
1171static LONG smartcard_Disconnect_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1177 WINPR_ASSERT(smartcard);
1179 WINPR_ASSERT(operation);
1181 call = &operation->call.hCardAndDisposition;
1183 ret.ReturnCode = wrap(smartcard, SCardDisconnect, operation->hCard, call->dwDisposition);
1184 scard_log_status_error_wlog(smartcard->log,
"SCardDisconnect", ret.ReturnCode);
1185 smartcard_trace_long_return_int(smartcard->log, &ret,
"Disconnect");
1187 return ret.ReturnCode;
1190static LONG smartcard_BeginTransaction_Call(scard_call_context* smartcard,
1191 WINPR_ATTR_UNUSED
wStream* out,
1196 WINPR_ASSERT(smartcard);
1198 WINPR_ASSERT(operation);
1200 ret.ReturnCode = wrap(smartcard, SCardBeginTransaction, operation->hCard);
1201 scard_log_status_error_wlog(smartcard->log,
"SCardBeginTransaction", ret.ReturnCode);
1202 smartcard_trace_long_return_int(smartcard->log, &ret,
"BeginTransaction");
1203 return ret.ReturnCode;
1206static LONG smartcard_EndTransaction_Call(scard_call_context* smartcard,
1207 WINPR_ATTR_UNUSED
wStream* out,
1213 WINPR_ASSERT(smartcard);
1215 WINPR_ASSERT(operation);
1217 call = &operation->call.hCardAndDisposition;
1219 ret.ReturnCode = wrap(smartcard, SCardEndTransaction, operation->hCard, call->dwDisposition);
1220 scard_log_status_error_wlog(smartcard->log,
"SCardEndTransaction", ret.ReturnCode);
1221 smartcard_trace_long_return_int(smartcard->log, &ret,
"EndTransaction");
1222 return ret.ReturnCode;
1225static LONG smartcard_State_Call(scard_call_context* smartcard,
wStream* out,
1231 WINPR_ASSERT(smartcard);
1233 WINPR_ASSERT(operation);
1235 ret.cbAtrLen = SCARD_ATR_LENGTH;
1236 ret.ReturnCode = wrap(smartcard, SCardState, operation->hCard, &ret.dwState, &ret.dwProtocol,
1237 (BYTE*)&ret.rgAtr, &ret.cbAtrLen);
1239 scard_log_status_error_wlog(smartcard->log,
"SCardState", ret.ReturnCode);
1240 status = smartcard_pack_state_return(out, &ret);
1241 if (status != SCARD_S_SUCCESS)
1244 return ret.ReturnCode;
1247static LONG smartcard_StatusA_Call(scard_call_context* smartcard,
wStream* out,
1252 DWORD cchReaderLen = 0;
1254 LPSTR mszReaderNames =
nullptr;
1257 WINPR_ASSERT(smartcard);
1259 WINPR_ASSERT(operation);
1261 call = &operation->call.status;
1263 call->cbAtrLen = 32;
1264 cbAtrLen = call->cbAtrLen;
1266 if (call->fmszReaderNamesIsNULL)
1269 cchReaderLen = SCARD_AUTOALLOCATE;
1271 status = ret.ReturnCode =
1272 wrap(smartcard, SCardStatusA, operation->hCard,
1273 call->fmszReaderNamesIsNULL ?
nullptr : (LPSTR)&mszReaderNames, &cchReaderLen,
1274 &ret.dwState, &ret.dwProtocol, cbAtrLen ? (BYTE*)&ret.pbAtr : nullptr, &cbAtrLen);
1276 scard_log_status_error_wlog(smartcard->log,
"SCardStatusA", status);
1277 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchReaderLen == SCARD_AUTOALLOCATE))
1278 return SCARD_F_UNKNOWN_ERROR;
1280 if (status == SCARD_S_SUCCESS)
1282 if (!call->fmszReaderNamesIsNULL)
1283 ret.mszReaderNames = (BYTE*)mszReaderNames;
1285 ret.cBytes = cchReaderLen;
1288 ret.cbAtrLen = cbAtrLen;
1291 status = smartcard_pack_status_return(out, &ret, FALSE);
1294 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1296 if (status != SCARD_S_SUCCESS)
1298 return ret.ReturnCode;
1301static LONG smartcard_StatusW_Call(scard_call_context* smartcard,
wStream* out,
1306 LPWSTR mszReaderNames =
nullptr;
1310 WINPR_ASSERT(smartcard);
1312 WINPR_ASSERT(operation);
1314 call = &operation->call.status;
1320 cbAtrLen = call->cbAtrLen = 32;
1322 if (call->fmszReaderNamesIsNULL)
1325 ret.cBytes = SCARD_AUTOALLOCATE;
1327 status = ret.ReturnCode =
1328 wrap(smartcard, SCardStatusW, operation->hCard,
1329 call->fmszReaderNamesIsNULL ?
nullptr : (LPWSTR)&mszReaderNames, &ret.cBytes,
1330 &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
1331 scard_log_status_error_wlog(smartcard->log,
"SCardStatusW", status);
1332 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cBytes == SCARD_AUTOALLOCATE))
1333 return SCARD_F_UNKNOWN_ERROR;
1336 if (status == SCARD_S_SUCCESS)
1338 if (!call->fmszReaderNamesIsNULL)
1339 ret.mszReaderNames = (BYTE*)mszReaderNames;
1341 ret.cbAtrLen = cbAtrLen;
1344 if (ret.cBytes != SCARD_AUTOALLOCATE)
1347 WINPR_ASSERT(ret.cBytes < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
1348 blen =
sizeof(WCHAR) * ret.cBytes;
1349 WINPR_ASSERT(blen <= UINT32_MAX);
1350 ret.cBytes = (UINT32)blen;
1353 status = smartcard_pack_status_return(out, &ret, TRUE);
1354 if (status != SCARD_S_SUCCESS)
1358 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1360 return ret.ReturnCode;
1363static LONG smartcard_Transmit_Call(scard_call_context* smartcard,
wStream* out,
1370 WINPR_ASSERT(smartcard);
1372 WINPR_ASSERT(operation);
1374 call = &operation->call.transmit;
1375 ret.cbRecvLength = 0;
1376 ret.pbRecvBuffer =
nullptr;
1378 if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
1380 if (call->cbRecvLength >= 66560)
1381 call->cbRecvLength = 66560;
1383 ret.cbRecvLength = call->cbRecvLength;
1384 ret.pbRecvBuffer = (BYTE*)malloc(ret.cbRecvLength);
1386 if (!ret.pbRecvBuffer)
1387 return STATUS_NO_MEMORY;
1390 ret.pioRecvPci = call->pioRecvPci;
1392 wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
1393 call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
1395 scard_log_status_error_wlog(smartcard->log,
"SCardTransmit", ret.ReturnCode);
1397 status = smartcard_pack_transmit_return(out, &ret);
1398 free(ret.pbRecvBuffer);
1400 if (status != SCARD_S_SUCCESS)
1402 return ret.ReturnCode;
1405static LONG smartcard_Control_Call(scard_call_context* smartcard,
wStream* out,
1412 WINPR_ASSERT(smartcard);
1414 WINPR_ASSERT(operation);
1416 call = &operation->call.control;
1417 ret.cbOutBufferSize = call->cbOutBufferSize;
1418 ret.pvOutBuffer = (BYTE*)malloc(call->cbOutBufferSize);
1420 if (!ret.pvOutBuffer)
1421 return SCARD_E_NO_MEMORY;
1424 wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
1425 call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
1426 scard_log_status_error_wlog(smartcard->log,
"SCardControl", ret.ReturnCode);
1427 status = smartcard_pack_control_return(out, &ret);
1429 free(ret.pvOutBuffer);
1430 if (status != SCARD_S_SUCCESS)
1432 return ret.ReturnCode;
1435static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard,
wStream* out,
1438 BOOL autoAllocate = FALSE;
1440 DWORD cbAttrLen = 0;
1441 LPBYTE pbAttr =
nullptr;
1445 WINPR_ASSERT(smartcard);
1446 WINPR_ASSERT(operation);
1448 call = &operation->call.getAttrib;
1450 if (!call->fpbAttrIsNULL)
1452 autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE);
1453 cbAttrLen = call->cbAttrLen;
1454 if (cbAttrLen && !autoAllocate)
1456 ret.pbAttr = (BYTE*)malloc(cbAttrLen);
1459 return SCARD_E_NO_MEMORY;
1462 pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
1466 wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
1467 scard_log_status_error_wlog(smartcard->log,
"SCardGetAttrib", ret.ReturnCode);
1468 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cbAttrLen == SCARD_AUTOALLOCATE))
1469 return SCARD_F_UNKNOWN_ERROR;
1471 ret.cbAttrLen = cbAttrLen;
1473 status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
1476 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
1482static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1488 WINPR_ASSERT(smartcard);
1490 WINPR_ASSERT(operation);
1492 call = &operation->call.setAttrib;
1494 ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
1496 scard_log_status_error_wlog(smartcard->log,
"SCardSetAttrib", ret.ReturnCode);
1497 smartcard_trace_long_return_int(smartcard->log, &ret,
"SetAttrib");
1499 return ret.ReturnCode;
1502static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard,
1503 WINPR_ATTR_UNUSED
wStream* out,
1506 LONG status = SCARD_S_SUCCESS;
1508 WINPR_ASSERT(smartcard);
1510 WINPR_UNUSED(operation);
1512 if (!smartcard->StartedEvent)
1513 smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
1515 if (!smartcard->StartedEvent)
1516 status = SCARD_E_NO_SERVICE;
1521static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard,
wStream* out,
1529 WINPR_ASSERT(smartcard);
1530 WINPR_ASSERT(operation);
1532 call = &operation->call.locateCardsByATRA;
1536 return STATUS_NO_MEMORY;
1538 for (UINT32 i = 0; i < call->cReaders; i++)
1541 state->szReader = call->rgReaderStates[i].szReader;
1542 state->dwCurrentState = call->rgReaderStates[i].dwCurrentState;
1543 state->dwEventState = call->rgReaderStates[i].dwEventState;
1544 state->cbAtr = call->rgReaderStates[i].cbAtr;
1545 CopyMemory(&(state->rgbAtr), &(call->rgReaderStates[i].rgbAtr), 36);
1548 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1549 0x000001F4, states, call->cReaders);
1551 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", status);
1552 for (UINT32 i = 0; i < call->cAtrs; i++)
1554 for (UINT32 j = 0; j < call->cReaders; j++)
1556 for (UINT32 k = 0; k < call->rgAtrMasks[i].cbAtr; k++)
1558 if ((call->rgAtrMasks[i].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]) !=
1559 (states[j].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]))
1564 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1569 ret.cReaders = call->cReaders;
1570 ret.rgReaderStates =
nullptr;
1572 if (ret.cReaders > 0)
1575 if (!ret.rgReaderStates)
1578 return STATUS_NO_MEMORY;
1581 for (UINT32 i = 0; i < ret.cReaders; i++)
1584 ret.rgReaderStates[i].dwCurrentState = state->dwCurrentState;
1585 ret.rgReaderStates[i].dwEventState = state->dwEventState;
1586 ret.rgReaderStates[i].cbAtr = state->cbAtr;
1587 CopyMemory(&(ret.rgReaderStates[i].rgbAtr), &(state->rgbAtr),
1588 sizeof(ret.rgReaderStates[i].rgbAtr));
1593 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1595 free(ret.rgReaderStates);
1596 if (status != SCARD_S_SUCCESS)
1598 return ret.ReturnCode;
1601LONG smartcard_irp_device_control_call(scard_call_context* ctx,
wStream* out, NTSTATUS* pIoStatus,
1606 size_t objectBufferLength = 0;
1610 WINPR_ASSERT(pIoStatus);
1611 WINPR_ASSERT(operation);
1613 const UINT32 ioControlCode = operation->ioControlCode;
1621 const size_t outMaxLen = MAX(2048, operation->outputBufferLength);
1622 if (!Stream_EnsureRemainingCapacity(out, outMaxLen))
1623 return SCARD_E_NO_MEMORY;
1626 Stream_Write_UINT32(out, 0);
1627 Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH);
1628 Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH);
1629 Stream_Write_UINT32(out, 0);
1632 switch (ioControlCode)
1634 case SCARD_IOCTL_ESTABLISHCONTEXT:
1635 result = smartcard_EstablishContext_Call(ctx, out, operation);
1638 case SCARD_IOCTL_RELEASECONTEXT:
1639 result = smartcard_ReleaseContext_Call(ctx, out, operation);
1642 case SCARD_IOCTL_ISVALIDCONTEXT:
1643 result = smartcard_IsValidContext_Call(ctx, out, operation);
1646 case SCARD_IOCTL_LISTREADERGROUPSA:
1647 result = smartcard_ListReaderGroupsA_Call(ctx, out, operation);
1650 case SCARD_IOCTL_LISTREADERGROUPSW:
1651 result = smartcard_ListReaderGroupsW_Call(ctx, out, operation);
1654 case SCARD_IOCTL_LISTREADERSA:
1655 result = smartcard_ListReadersA_Call(ctx, out, operation);
1658 case SCARD_IOCTL_LISTREADERSW:
1659 result = smartcard_ListReadersW_Call(ctx, out, operation);
1662 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1663 result = smartcard_IntroduceReaderGroupA_Call(ctx, out, operation);
1666 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1667 result = smartcard_IntroduceReaderGroupW_Call(ctx, out, operation);
1670 case SCARD_IOCTL_FORGETREADERGROUPA:
1671 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
1674 case SCARD_IOCTL_FORGETREADERGROUPW:
1675 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
1678 case SCARD_IOCTL_INTRODUCEREADERA:
1679 result = smartcard_IntroduceReaderA_Call(ctx, out, operation);
1682 case SCARD_IOCTL_INTRODUCEREADERW:
1683 result = smartcard_IntroduceReaderW_Call(ctx, out, operation);
1686 case SCARD_IOCTL_FORGETREADERA:
1687 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
1690 case SCARD_IOCTL_FORGETREADERW:
1691 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
1694 case SCARD_IOCTL_ADDREADERTOGROUPA:
1695 result = smartcard_AddReaderToGroupA_Call(ctx, out, operation);
1698 case SCARD_IOCTL_ADDREADERTOGROUPW:
1699 result = smartcard_AddReaderToGroupW_Call(ctx, out, operation);
1702 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1703 result = smartcard_RemoveReaderFromGroupA_Call(ctx, out, operation);
1706 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1707 result = smartcard_RemoveReaderFromGroupW_Call(ctx, out, operation);
1710 case SCARD_IOCTL_LOCATECARDSA:
1711 result = smartcard_LocateCardsA_Call(ctx, out, operation);
1714 case SCARD_IOCTL_LOCATECARDSW:
1715 result = smartcard_LocateCardsW_Call(ctx, out, operation);
1718 case SCARD_IOCTL_GETSTATUSCHANGEA:
1719 result = smartcard_GetStatusChangeA_Call(ctx, out, operation);
1722 case SCARD_IOCTL_GETSTATUSCHANGEW:
1723 result = smartcard_GetStatusChangeW_Call(ctx, out, operation);
1726 case SCARD_IOCTL_CANCEL:
1727 result = smartcard_Cancel_Call(ctx, out, operation);
1730 case SCARD_IOCTL_CONNECTA:
1731 result = smartcard_ConnectA_Call(ctx, out, operation);
1734 case SCARD_IOCTL_CONNECTW:
1735 result = smartcard_ConnectW_Call(ctx, out, operation);
1738 case SCARD_IOCTL_RECONNECT:
1739 result = smartcard_Reconnect_Call(ctx, out, operation);
1742 case SCARD_IOCTL_DISCONNECT:
1743 result = smartcard_Disconnect_Call(ctx, out, operation);
1746 case SCARD_IOCTL_BEGINTRANSACTION:
1747 result = smartcard_BeginTransaction_Call(ctx, out, operation);
1750 case SCARD_IOCTL_ENDTRANSACTION:
1751 result = smartcard_EndTransaction_Call(ctx, out, operation);
1754 case SCARD_IOCTL_STATE:
1755 result = smartcard_State_Call(ctx, out, operation);
1758 case SCARD_IOCTL_STATUSA:
1759 result = smartcard_StatusA_Call(ctx, out, operation);
1762 case SCARD_IOCTL_STATUSW:
1763 result = smartcard_StatusW_Call(ctx, out, operation);
1766 case SCARD_IOCTL_TRANSMIT:
1767 result = smartcard_Transmit_Call(ctx, out, operation);
1770 case SCARD_IOCTL_CONTROL:
1771 result = smartcard_Control_Call(ctx, out, operation);
1774 case SCARD_IOCTL_GETATTRIB:
1775 result = smartcard_GetAttrib_Call(ctx, out, operation);
1778 case SCARD_IOCTL_SETATTRIB:
1779 result = smartcard_SetAttrib_Call(ctx, out, operation);
1782 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
1783 result = smartcard_AccessStartedEvent_Call(ctx, out, operation);
1786 case SCARD_IOCTL_LOCATECARDSBYATRA:
1787 result = smartcard_LocateCardsByATRA_Call(ctx, out, operation);
1790 case SCARD_IOCTL_LOCATECARDSBYATRW:
1791 result = smartcard_LocateCardsW_Call(ctx, out, operation);
1794 case SCARD_IOCTL_READCACHEA:
1795 result = smartcard_ReadCacheA_Call(ctx, out, operation);
1798 case SCARD_IOCTL_READCACHEW:
1799 result = smartcard_ReadCacheW_Call(ctx, out, operation);
1802 case SCARD_IOCTL_WRITECACHEA:
1803 result = smartcard_WriteCacheA_Call(ctx, out, operation);
1806 case SCARD_IOCTL_WRITECACHEW:
1807 result = smartcard_WriteCacheW_Call(ctx, out, operation);
1810 case SCARD_IOCTL_GETTRANSMITCOUNT:
1811 result = smartcard_GetTransmitCount_Call(ctx, out, operation);
1814 case SCARD_IOCTL_RELEASETARTEDEVENT:
1815 result = smartcard_ReleaseStartedEvent_Call(ctx, out, operation);
1818 case SCARD_IOCTL_GETREADERICON:
1819 result = smartcard_GetReaderIcon_Call(ctx, out, operation);
1822 case SCARD_IOCTL_GETDEVICETYPEID:
1823 result = smartcard_GetDeviceTypeId_Call(ctx, out, operation);
1827 result = STATUS_UNSUCCESSFUL;
1837 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
1838 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
1840 offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
1841 const LONG rc = smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
1842 if (rc != SCARD_S_SUCCESS)
1846 if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
1847 (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
1848 (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
1850 WLog_Print(ctx->log, WLOG_WARN,
1851 "IRP failure: %s (0x%08" PRIX32
"), status: %s (0x%08" PRIX32
")",
1852 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
1853 SCardGetErrorString(result), WINPR_CXX_COMPAT_CAST(UINT32, result));
1856 *pIoStatus = STATUS_SUCCESS;
1858 if ((result & 0xC0000000L) == 0xC0000000L)
1861 *pIoStatus = result;
1862 WLog_Print(ctx->log, WLOG_WARN,
1863 "IRP failure: %s (0x%08" PRIX32
"), ntstatus: 0x%08" PRIX32
"",
1864 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
1865 WINPR_CXX_COMPAT_CAST(UINT32, result));
1868 Stream_SealLength(out);
1869 size_t outputBufferLength = Stream_Length(out);
1870 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1871 outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1872 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1873 objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
1874 WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
1875 WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
1876 if (!Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH))
1877 return SCARD_E_BAD_SEEK;
1886 if (outputBufferLength > operation->outputBufferLength)
1888 WLog_Print(ctx->log, WLOG_WARN,
1889 "IRP warn: expected outputBufferLength %" PRIu32
", but current limit %" PRIuz
1890 ", respond with STATUS_BUFFER_TOO_SMALL",
1891 operation->outputBufferLength, outputBufferLength);
1893 *pIoStatus = STATUS_BUFFER_TOO_SMALL;
1894 result = *pIoStatus;
1895 outputBufferLength = 0;
1896 objectBufferLength = 0;
1900 Stream_Write_UINT32(out, (UINT32)outputBufferLength);
1901 smartcard_pack_common_type_header(out);
1902 smartcard_pack_private_type_header(
1903 out, (UINT32)objectBufferLength);
1904 Stream_Write_INT32(out, result);
1905 if (!Stream_SetPosition(out, Stream_Length(out)))
1906 return SCARD_E_BAD_SEEK;
1907 return SCARD_S_SUCCESS;
1910void context_free(
void* arg)
1912 struct s_scard_context_element* element = arg;
1916 if (element->fn_free)
1917 element->fn_free(element->context);
1921scard_call_context* smartcard_call_context_new(
const rdpSettings* settings)
1924 scard_call_context* ctx =
nullptr;
1926 WINPR_ASSERT(settings);
1927 ctx = calloc(1,
sizeof(scard_call_context));
1931 ctx->log = WLog_Get(SCARD_TAG);
1932 WINPR_ASSERT(ctx->log);
1934 ctx->stopEvent = CreateEventA(
nullptr, TRUE, FALSE,
nullptr);
1935 if (!ctx->stopEvent)
1938 ctx->names = LinkedList_New();
1942#if defined(WITH_SMARTCARD_EMULATE)
1946 if (ctx->useEmulatedCard)
1948#if defined(WITH_SMARTCARD_EMULATE)
1949 ctx->emulation = Emulate_New(settings);
1950 if (!ctx->emulation)
1953 WLog_Print(ctx->log, WLOG_ERROR,
"Smartcard emulation requested, but not supported!");
1962 ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
1964 if (!ctx->hWinSCardLibrary)
1966 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard library: '%s'",
1971 if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
1973 ctx->pWinSCardApi = &ctx->WinSCardApi;
1977 ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
1980 if (!ctx->pWinSCardApi)
1982 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard API!");
1987 ctx->rgSCardContextList = HashTable_New(FALSE);
1988 if (!ctx->rgSCardContextList)
1991 obj = HashTable_ValueObject(ctx->rgSCardContextList);
1997 WINPR_PRAGMA_DIAG_PUSH
1998 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1999 smartcard_call_context_free(ctx);
2000 WINPR_PRAGMA_DIAG_POP
2004void smartcard_call_context_free(scard_call_context* ctx)
2009 smartcard_call_context_signal_stop(ctx, FALSE);
2011 LinkedList_Free(ctx->names);
2012 if (ctx->StartedEvent)
2014 WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
2015 wrap_raw(ctx, SCardReleaseStartedEvent);
2018 if (ctx->useEmulatedCard)
2020#ifdef WITH_SMARTCARD_EMULATE
2023 Emulate_Free(ctx->emulation);
2024 ctx->emulation =
nullptr;
2029 if (ctx->hWinSCardLibrary)
2032 FreeLibrary(ctx->hWinSCardLibrary);
2033 ctx->hWinSCardLibrary =
nullptr;
2036 ctx->pWinSCardApi =
nullptr;
2038 HashTable_Free(ctx->rgSCardContextList);
2039 (void)CloseHandle(ctx->stopEvent);
2043BOOL smartcard_call_context_add(scard_call_context* ctx,
const char* name)
2047 return LinkedList_AddLast(ctx->names, name);
2050BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2053 if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
2055 wrap(ctx, SCardCancel, hContext);
2060BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2063 wrap(ctx, SCardReleaseContext, hContext);
2067BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
2072 smartcard_call_context_signal_stop(ctx, FALSE);
2073 HashTable_Clear(ctx->rgSCardContextList);
2077BOOL smarcard_call_set_callbacks(scard_call_context* ctx,
void* userdata,
2078 void* (*fn_new)(
void*, SCARDCONTEXT),
void (*fn_free)(
void*))
2081 ctx->userdata = userdata;
2082 ctx->fn_new = fn_new;
2083 ctx->fn_free = fn_free;
2087void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2089 struct s_scard_context_element* element =
nullptr;
2092 element = HashTable_GetItemValue(ctx->rgSCardContextList, (
void*)hContext);
2095 return element->context;
2098BOOL smartcard_call_is_configured(scard_call_context* ctx)
2102#if defined(WITH_SMARTCARD_EMULATE)
2103 if (ctx->useEmulatedCard)
2104 return Emulate_IsConfigured(ctx->emulation);
2110BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
2114 if (!ctx->stopEvent)
2118 return ResetEvent(ctx->stopEvent);
2120 return SetEvent(ctx->stopEvent);
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