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>
35#include <winpr/synch.h>
36#include <winpr/sysinfo.h>
37#include <winpr/thread.h>
38#include <winpr/collections.h>
43#include <freerdp/freerdp.h>
44#include <freerdp/channels/rdpdr.h>
45#include <freerdp/channels/scard.h>
47#include <freerdp/utils/rdpdr_utils.h>
48#include <freerdp/utils/smartcard_pack.h>
49#include <freerdp/utils/smartcard_call.h>
51#include "smartcard_pack.h"
53#include <freerdp/log.h>
54#define SCARD_TAG FREERDP_TAG("utils.smartcard.call")
56#if defined(WITH_SMARTCARD_EMULATE)
57#include <freerdp/emulate/scard/smartcard_emulate.h>
64#define wrap_raw(ctx, fkt, ...) \
65 ((ctx)->useEmulatedCard ? Emulate_##fkt((ctx)->emulation, ##__VA_ARGS__) \
66 : (ctx)->pWinSCardApi->pfn##fkt(__VA_ARGS__))
67#define wrap_ptr(ctx, fkt, ...) wrap_raw(ctx, fkt, ##__VA_ARGS__)
69#define wrap_raw(ctx, fkt, ...) \
70 ((ctx)->useEmulatedCard ? SCARD_F_INTERNAL_ERROR : (ctx)->pWinSCardApi->pfn##fkt(__VA_ARGS__))
71#define wrap_ptr(ctx, fkt, ...) \
72 ((ctx)->useEmulatedCard ? nullptr : (ctx)->pWinSCardApi->pfn##fkt(__VA_ARGS__))
76#define wrap(ctx, fkt, ...) wrap_raw(ctx, fkt, ##__VA_ARGS__)
78#define wrap(ctx, fkt, ...) \
80 LONG defstatus = wrap_raw(ctx, fkt, ##__VA_ARGS__); \
81 if (defstatus != SCARD_S_SUCCESS) \
82 WLog_Print(ctx->log, WLOG_TRACE, "[" #fkt "] failed with %s", \
83 SCardGetErrorString(defstatus)); \
88struct s_scard_call_context
93 wHashTable* rgSCardContextList;
94#if defined(WITH_SMARTCARD_EMULATE)
95 SmartcardEmulationContext* emulation;
97 HANDLE hWinSCardLibrary;
103 void* (*fn_new)(
void*, SCARDCONTEXT);
104 void (*fn_free)(
void*);
109 wHashTable* handleStates;
110 HANDLE watchdogStopEvent;
111 HANDLE watchdogThread;
112 UINT64 transactionTimeout;
115struct s_scard_context_element
118 void (*fn_free)(
void*);
121static void context_free(
void* arg);
125#define SCARD_TRANSACTION_IDLE_TIMEOUT_MS 5000
126#define SCARD_TRANSACTION_WATCHDOG_INTERVAL_MS 250
127#define SCARD_TRANSACTION_WATCHDOG_MAX_EXPIRED 32
134 UINT32 pendingBegins;
135 UINT32 abandonedBegins;
144 SCARDHANDLE handles[SCARD_TRANSACTION_WATCHDOG_MAX_EXPIRED];
145} scard_expired_transactions;
147static void smartcard_handle_activity_begin(scard_call_context* ctx, UINT32 ioControlCode,
152 if (!ctx->handleStates || !hCard)
155 HashTable_Lock(ctx->handleStates);
156 scard_handle_state* state = HashTable_GetItemValue(ctx->handleStates, (
void*)hCard);
159 state = calloc(1,
sizeof(scard_handle_state));
160 if (state && !HashTable_Insert(ctx->handleStates, (
void*)hCard, state))
168 state->activeCalls++;
169 state->lastActivity = GetTickCount64();
171 switch (ioControlCode)
173 case SCARD_IOCTL_BEGINTRANSACTION:
174 state->pendingBegins++;
176 case SCARD_IOCTL_ENDTRANSACTION:
178 if (state->inTransaction)
179 state->inTransaction = FALSE;
180 else if (state->pendingBegins > state->abandonedBegins)
181 state->abandonedBegins++;
188 HashTable_Unlock(ctx->handleStates);
192static BOOL smartcard_handle_activity_end(scard_call_context* ctx, UINT32 ioControlCode,
193 SCARDHANDLE hCard, LONG result)
195 BOOL abandoned = FALSE;
199 if (!ctx->handleStates || !hCard)
202 HashTable_Lock(ctx->handleStates);
203 scard_handle_state* state = HashTable_GetItemValue(ctx->handleStates, (
void*)hCard);
206 if (state->activeCalls > 0)
207 state->activeCalls--;
208 state->lastActivity = GetTickCount64();
210 switch (ioControlCode)
212 case SCARD_IOCTL_BEGINTRANSACTION:
213 if (state->pendingBegins > 0)
214 state->pendingBegins--;
215 if (state->abandonedBegins > 0)
217 state->abandonedBegins--;
218 abandoned = (result == SCARD_S_SUCCESS);
220 else if (result == SCARD_S_SUCCESS)
221 state->inTransaction = TRUE;
223 case SCARD_IOCTL_DISCONNECT:
224 if (result == SCARD_S_SUCCESS)
226 state->inTransaction = FALSE;
227 state->disconnected = TRUE;
234 if (state->disconnected && (state->activeCalls == 0))
235 HashTable_Remove(ctx->handleStates, (
void*)hCard);
237 HashTable_Unlock(ctx->handleStates);
241static BOOL smartcard_collect_expired_transaction(
const void* key,
void* value,
void* arg)
243 scard_handle_state* state = value;
244 scard_expired_transactions* expired = arg;
247 WINPR_ASSERT(expired);
249 if (!state->inTransaction || (state->activeCalls > 0))
251 if (expired->now - state->lastActivity < expired->timeout)
253 if (expired->count >= ARRAYSIZE(expired->handles))
256 state->inTransaction = FALSE;
257 expired->handles[expired->count++] = (SCARDHANDLE)key;
261static DWORD WINAPI smartcard_transaction_watchdog(LPVOID arg)
263 scard_call_context* ctx = arg;
267 while (WaitForSingleObject(ctx->watchdogStopEvent, SCARD_TRANSACTION_WATCHDOG_INTERVAL_MS) ==
270 scard_expired_transactions expired = WINPR_C_ARRAY_INIT;
271 expired.now = GetTickCount64();
272 expired.timeout = ctx->transactionTimeout;
274 if (!HashTable_Foreach(ctx->handleStates, smartcard_collect_expired_transaction, &expired))
275 WLog_Print(ctx->log, WLOG_DEBUG,
276 "more idle transactions than handled in one round, continuing next round");
279 for (
size_t x = 0; x < expired.count; x++)
281 const SCARDHANDLE hCard = expired.handles[x];
283 WLog_Print(ctx->log, WLOG_WARN,
284 "transaction on hCard 0x%08" PRIxz
" idle for more than %" PRIu64
285 " ms, ending it and resetting the card like Windows does",
286 (
size_t)hCard, ctx->transactionTimeout);
288 const LONG rc = wrap(ctx, SCardEndTransaction, hCard, SCARD_RESET_CARD);
289 if (rc == SCARD_E_INVALID_HANDLE)
290 HashTable_Remove(ctx->handleStates, (
void*)hCard);
298static UINT64 smartcard_transaction_timeout(
void)
301 const char* value = getenv(
"FREERDP_SCARD_TRANSACTION_TIMEOUT_MS");
302 if (!value || !*value)
303 return SCARD_TRANSACTION_IDLE_TIMEOUT_MS;
307 const unsigned long long timeout = strtoull(value, &end, 10);
308 if ((errno != 0) || !end || (*end !=
'\0'))
309 return SCARD_TRANSACTION_IDLE_TIMEOUT_MS;
313static BOOL smartcard_transaction_watchdog_start(scard_call_context* ctx)
317 if (ctx->useEmulatedCard)
320 ctx->handleStates = HashTable_New(TRUE);
321 if (!ctx->handleStates)
325 wObject* obj = HashTable_ValueObject(ctx->handleStates);
330 ctx->transactionTimeout = smartcard_transaction_timeout();
331 if (ctx->transactionTimeout == 0)
333 WLog_Print(ctx->log, WLOG_DEBUG,
"idle transaction watchdog disabled");
337 ctx->watchdogStopEvent = CreateEventA(
nullptr, TRUE, FALSE,
nullptr);
338 if (!ctx->watchdogStopEvent)
341 ctx->watchdogThread = CreateThread(
nullptr, 0, smartcard_transaction_watchdog, ctx, 0,
nullptr);
342 if (!ctx->watchdogThread)
345 WLog_Print(ctx->log, WLOG_DEBUG,
"idle transaction watchdog started, timeout %" PRIu64
" ms",
346 ctx->transactionTimeout);
350static void smartcard_transaction_watchdog_stop(scard_call_context* ctx)
354 if (ctx->watchdogThread)
356 (void)SetEvent(ctx->watchdogStopEvent);
357 (void)WaitForSingleObject(ctx->watchdogThread, INFINITE);
358 (void)CloseHandle(ctx->watchdogThread);
359 ctx->watchdogThread =
nullptr;
361 if (ctx->watchdogStopEvent)
363 (void)CloseHandle(ctx->watchdogStopEvent);
364 ctx->watchdogStopEvent =
nullptr;
368WINPR_ATTR_NODISCARD WINPR_ATTR_NODISCARD
static LONG
369smartcard_EstablishContext_Call(scard_call_context* smartcard,
wStream* out,
372 SCARDCONTEXT hContext = WINPR_C_ARRAY_INIT;
375 LONG status = ret.ReturnCode =
376 wrap(smartcard, SCardEstablishContext, call->dwScope,
nullptr,
nullptr, &hContext);
378 if (ret.ReturnCode == SCARD_S_SUCCESS)
380 const void* key = (
void*)(
size_t)hContext;
381 struct s_scard_context_element* pContext =
382 calloc(1,
sizeof(
struct s_scard_context_element));
384 return STATUS_NO_MEMORY;
386 pContext->fn_free = smartcard->fn_free;
388 if (smartcard->fn_new)
390 pContext->context = smartcard->fn_new(smartcard->userdata, hContext);
391 if (!pContext->context)
394 return STATUS_NO_MEMORY;
398 if (!HashTable_Insert(smartcard->rgSCardContextList, key, (
void*)pContext))
400 WLog_Print(smartcard->log, WLOG_ERROR,
"HashTable_Insert failed!");
401 context_free(pContext);
402 return STATUS_INTERNAL_ERROR;
407 return scard_log_status_error_wlog(smartcard->log,
"SCardEstablishContext", status);
411 smartcard_scard_context_native_to_redir(&(ret.hContext), hContext);
413 status = smartcard_pack_establish_context_return(out, &ret);
414 if (status != SCARD_S_SUCCESS)
416 return scard_log_status_error_wlog(smartcard->log,
417 "smartcard_pack_establish_context_return", status);
420 return ret.ReturnCode;
423WINPR_ATTR_NODISCARD
static LONG smartcard_ReleaseContext_Call(scard_call_context* smartcard,
424 WINPR_ATTR_UNUSED
wStream* out,
429 WINPR_ASSERT(smartcard);
431 WINPR_ASSERT(operation);
433 ret.ReturnCode = wrap(smartcard, SCardReleaseContext, operation->hContext);
435 if (ret.ReturnCode == SCARD_S_SUCCESS)
436 HashTable_Remove(smartcard->rgSCardContextList, (
void*)operation->hContext);
439 return scard_log_status_error_wlog(smartcard->log,
"SCardReleaseContext", ret.ReturnCode);
442 smartcard_trace_long_return_int(smartcard->log, &ret,
"ReleaseContext");
443 return ret.ReturnCode;
446WINPR_ATTR_NODISCARD
static LONG smartcard_IsValidContext_Call(scard_call_context* smartcard,
447 WINPR_ATTR_UNUSED
wStream* out,
452 WINPR_ASSERT(smartcard);
454 WINPR_ASSERT(operation);
456 ret.ReturnCode = wrap(smartcard, SCardIsValidContext, operation->hContext);
457 smartcard_trace_long_return_int(smartcard->log, &ret,
"IsValidContext");
458 return ret.ReturnCode;
461WINPR_ATTR_NODISCARD
static LONG smartcard_ListReaderGroupsA_Call(scard_call_context* smartcard,
467 LPSTR mszGroups =
nullptr;
470 WINPR_ASSERT(smartcard);
472 WINPR_ASSERT(operation);
474 cchGroups = SCARD_AUTOALLOCATE;
476 wrap(smartcard, SCardListReaderGroupsA, operation->hContext, (LPSTR)&mszGroups, &cchGroups);
477 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchGroups == SCARD_AUTOALLOCATE))
478 return SCARD_F_UNKNOWN_ERROR;
480 ret.msz = (BYTE*)mszGroups;
481 ret.cBytes = cchGroups;
483 status = smartcard_pack_list_reader_groups_return(out, &ret, FALSE);
485 if (status != SCARD_S_SUCCESS)
489 wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
491 return ret.ReturnCode;
494WINPR_ATTR_NODISCARD
static LONG smartcard_ListReaderGroupsW_Call(scard_call_context* smartcard,
500 LPWSTR mszGroups =
nullptr;
503 WINPR_ASSERT(smartcard);
505 WINPR_ASSERT(operation);
507 cchGroups = SCARD_AUTOALLOCATE;
508 status = ret.ReturnCode = wrap(smartcard, SCardListReaderGroupsW, operation->hContext,
509 (LPWSTR)&mszGroups, &cchGroups);
510 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchGroups == SCARD_AUTOALLOCATE))
511 return SCARD_F_UNKNOWN_ERROR;
513 ret.msz = (BYTE*)mszGroups;
515 WINPR_ASSERT(cchGroups < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
516 const size_t blen =
sizeof(WCHAR) * cchGroups;
517 WINPR_ASSERT(blen <= UINT32_MAX);
518 ret.cBytes = (UINT32)blen;
520 if (status != SCARD_S_SUCCESS)
523 status = smartcard_pack_list_reader_groups_return(out, &ret, TRUE);
525 if (status != SCARD_S_SUCCESS)
529 wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
531 return ret.ReturnCode;
535static BOOL filter_match(wLinkedList* list, LPCSTR reader,
size_t readerLen)
540 LinkedList_Enumerator_Reset(list);
542 while (LinkedList_Enumerator_MoveNext(list))
544 const char* filter = LinkedList_Enumerator_Current(list);
548 if (strstr(reader, filter) !=
nullptr)
557static DWORD filter_device_by_name_a(wLinkedList* list, LPSTR* mszReaders, DWORD cchReaders)
562 if (*mszReaders ==
nullptr || LinkedList_Count(list) < 1)
567 LPCSTR rreader = &(*mszReaders)[rpos];
568 LPSTR wreader = &(*mszReaders)[wpos];
569 size_t readerLen = strnlen(rreader, cchReaders - rpos);
571 rpos += readerLen + 1;
573 if (filter_match(list, rreader, readerLen))
575 if (rreader != wreader)
576 memmove(wreader, rreader, readerLen + 1);
578 wpos += readerLen + 1;
580 }
while (rpos < cchReaders);
585 if (wpos >= cchReaders)
588 (*mszReaders)[wpos++] =
'\0';
595static DWORD filter_device_by_name_w(wLinkedList* list, LPWSTR* mszReaders, DWORD cchReaders)
598 LPSTR readers =
nullptr;
600 if (LinkedList_Count(list) < 1)
603 readers = ConvertMszWCharNToUtf8Alloc(*mszReaders, cchReaders,
nullptr);
611 *mszReaders =
nullptr;
612 rc = filter_device_by_name_a(list, &readers, cchReaders);
614 *mszReaders = ConvertMszUtf8NToWCharAlloc(readers, rc,
nullptr);
622WINPR_ATTR_NODISCARD
static LONG smartcard_ListReadersA_Call(scard_call_context* smartcard,
627 LPSTR mszReaders =
nullptr;
629 WINPR_ASSERT(smartcard);
631 WINPR_ASSERT(operation);
634 DWORD cchReaders = SCARD_AUTOALLOCATE;
635 LONG status = ret.ReturnCode = wrap(smartcard, SCardListReadersA, operation->hContext,
636 (LPCSTR)call->mszGroups, (LPSTR)&mszReaders, &cchReaders);
637 if (status == SCARD_S_SUCCESS)
639 if (cchReaders == SCARD_AUTOALLOCATE)
640 status = SCARD_F_UNKNOWN_ERROR;
643 if (status != SCARD_S_SUCCESS)
645 (void)scard_log_status_error_wlog(smartcard->log,
"SCardListReadersA", status);
646 return smartcard_pack_list_readers_return(out, &ret, FALSE);
649 void* original = mszReaders;
650 cchReaders = filter_device_by_name_a(smartcard->names, &mszReaders, cchReaders);
651 ret.msz = (BYTE*)mszReaders;
652 ret.cBytes = cchReaders;
654 status = smartcard_pack_list_readers_return(out, &ret, FALSE);
656 wrap(smartcard, SCardFreeMemory, operation->hContext, original);
658 if (status != SCARD_S_SUCCESS)
659 return scard_log_status_error_wlog(smartcard->log,
"smartcard_pack_list_readers_return",
662 return ret.ReturnCode;
665WINPR_ATTR_NODISCARD
static LONG smartcard_ListReadersW_Call(scard_call_context* smartcard,
671 DWORD cchReaders = 0;
687 WINPR_ASSERT(smartcard);
688 WINPR_ASSERT(operation);
690 call = &operation->call.listReaders;
692 string.bp = call->mszGroups;
693 cchReaders = SCARD_AUTOALLOCATE;
694 status = ret.ReturnCode = wrap(smartcard, SCardListReadersW, operation->hContext,
string.wz,
695 (LPWSTR)&mszReaders.pw, &cchReaders);
696 if (status == SCARD_S_SUCCESS)
698 if (cchReaders == SCARD_AUTOALLOCATE)
699 status = SCARD_F_UNKNOWN_ERROR;
702 if (status != SCARD_S_SUCCESS)
704 (void)scard_log_status_error_wlog(smartcard->log,
"SCardListReadersW", status);
705 return smartcard_pack_list_readers_return(out, &ret, TRUE);
708 void* original = mszReaders.pb;
709 cchReaders = filter_device_by_name_w(smartcard->names, &mszReaders.pw, cchReaders);
710 ret.msz = mszReaders.pb;
711 ret.cBytes = cchReaders *
sizeof(WCHAR);
712 status = smartcard_pack_list_readers_return(out, &ret, TRUE);
715 wrap(smartcard, SCardFreeMemory, operation->hContext, original);
717 if (status != SCARD_S_SUCCESS)
720 return ret.ReturnCode;
723WINPR_ATTR_NODISCARD
static LONG
724smartcard_IntroduceReaderGroupA_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
730 WINPR_ASSERT(smartcard);
732 WINPR_ASSERT(operation);
734 call = &operation->call.contextAndStringA;
735 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupA, operation->hContext, call->sz);
736 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderGroupA", ret.ReturnCode);
737 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderGroupA");
738 return ret.ReturnCode;
741WINPR_ATTR_NODISCARD
static LONG
742smartcard_IntroduceReaderGroupW_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
748 WINPR_ASSERT(smartcard);
750 WINPR_ASSERT(operation);
752 call = &operation->call.contextAndStringW;
753 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupW, operation->hContext, call->sz);
754 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderGroupW", ret.ReturnCode);
755 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderGroupW");
756 return ret.ReturnCode;
759WINPR_ATTR_NODISCARD
static LONG smartcard_IntroduceReaderA_Call(scard_call_context* smartcard,
760 WINPR_ATTR_UNUSED
wStream* out,
766 WINPR_ASSERT(smartcard);
768 WINPR_ASSERT(operation);
770 call = &operation->call.contextAndTwoStringA;
772 wrap(smartcard, SCardIntroduceReaderA, operation->hContext, call->sz1, call->sz2);
773 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderA", ret.ReturnCode);
774 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderA");
775 return ret.ReturnCode;
778WINPR_ATTR_NODISCARD
static LONG smartcard_IntroduceReaderW_Call(scard_call_context* smartcard,
779 WINPR_ATTR_UNUSED
wStream* out,
785 WINPR_ASSERT(smartcard);
787 WINPR_ASSERT(operation);
789 call = &operation->call.contextAndTwoStringW;
791 wrap(smartcard, SCardIntroduceReaderW, operation->hContext, call->sz1, call->sz2);
792 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderW", ret.ReturnCode);
793 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderW");
794 return ret.ReturnCode;
797WINPR_ATTR_NODISCARD
static LONG smartcard_ForgetReaderA_Call(scard_call_context* smartcard,
798 WINPR_ATTR_UNUSED
wStream* out,
804 WINPR_ASSERT(smartcard);
806 WINPR_ASSERT(operation);
808 call = &operation->call.contextAndStringA;
809 ret.ReturnCode = wrap(smartcard, SCardForgetReaderA, operation->hContext, call->sz);
810 scard_log_status_error_wlog(smartcard->log,
"SCardForgetReaderA", ret.ReturnCode);
811 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardForgetReaderA");
812 return ret.ReturnCode;
815WINPR_ATTR_NODISCARD
static LONG smartcard_ForgetReaderW_Call(scard_call_context* smartcard,
816 WINPR_ATTR_UNUSED
wStream* out,
822 WINPR_ASSERT(smartcard);
824 WINPR_ASSERT(operation);
826 call = &operation->call.contextAndStringW;
827 ret.ReturnCode = wrap(smartcard, SCardForgetReaderW, operation->hContext, call->sz);
828 scard_log_status_error_wlog(smartcard->log,
"SCardForgetReaderW", ret.ReturnCode);
829 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardForgetReaderW");
830 return ret.ReturnCode;
833WINPR_ATTR_NODISCARD
static LONG smartcard_AddReaderToGroupA_Call(scard_call_context* smartcard,
834 WINPR_ATTR_UNUSED
wStream* out,
840 WINPR_ASSERT(smartcard);
842 WINPR_ASSERT(operation);
844 call = &operation->call.contextAndTwoStringA;
846 wrap(smartcard, SCardAddReaderToGroupA, operation->hContext, call->sz1, call->sz2);
847 scard_log_status_error_wlog(smartcard->log,
"SCardAddReaderToGroupA", ret.ReturnCode);
848 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardAddReaderToGroupA");
849 return ret.ReturnCode;
852WINPR_ATTR_NODISCARD
static LONG smartcard_AddReaderToGroupW_Call(scard_call_context* smartcard,
853 WINPR_ATTR_UNUSED
wStream* out,
859 WINPR_ASSERT(smartcard);
861 WINPR_ASSERT(operation);
863 call = &operation->call.contextAndTwoStringW;
865 wrap(smartcard, SCardAddReaderToGroupW, operation->hContext, call->sz1, call->sz2);
866 scard_log_status_error_wlog(smartcard->log,
"SCardAddReaderToGroupW", ret.ReturnCode);
867 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardAddReaderToGroupA");
868 return ret.ReturnCode;
871WINPR_ATTR_NODISCARD
static LONG
872smartcard_RemoveReaderFromGroupA_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
878 WINPR_ASSERT(smartcard);
880 WINPR_ASSERT(operation);
882 call = &operation->call.contextAndTwoStringA;
884 wrap(smartcard, SCardRemoveReaderFromGroupA, operation->hContext, call->sz1, call->sz2);
885 scard_log_status_error_wlog(smartcard->log,
"SCardRemoveReaderFromGroupA", ret.ReturnCode);
886 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardRemoveReaderFromGroupA");
887 return ret.ReturnCode;
890WINPR_ATTR_NODISCARD
static LONG
891smartcard_RemoveReaderFromGroupW_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
897 WINPR_ASSERT(smartcard);
899 WINPR_ASSERT(operation);
901 call = &operation->call.contextAndTwoStringW;
903 wrap(smartcard, SCardRemoveReaderFromGroupW, operation->hContext, call->sz1, call->sz2);
904 scard_log_status_error_wlog(smartcard->log,
"SCardRemoveReaderFromGroupW", ret.ReturnCode);
905 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardRemoveReaderFromGroupW");
906 return ret.ReturnCode;
909WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsA_Call(scard_call_context* smartcard,
917 WINPR_ASSERT(smartcard);
918 WINPR_ASSERT(operation);
920 call = &operation->call.locateCardsA;
922 ret.ReturnCode = wrap(smartcard, SCardLocateCardsA, operation->hContext, call->mszCards,
923 call->rgReaderStates, call->cReaders);
924 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsA", ret.ReturnCode);
925 ret.rgReaderStates =
nullptr;
927 if (call->cReaders > 0)
932 if (!ret.rgReaderStates)
933 return STATUS_NO_MEMORY;
934 ret.cReaders = call->cReaders;
937 for (UINT32 x = 0; x < ret.cReaders; x++)
942 cur->dwCurrentState = cstate->dwCurrentState;
943 cur->dwEventState = cstate->dwEventState;
944 cur->cbAtr = cstate->cbAtr;
945 CopyMemory(&(cur->rgbAtr), &(cstate->rgbAtr),
sizeof(cur->rgbAtr));
946 if (!smartcard_reader_state_return_is_valid(x, cur))
948 free(ret.rgReaderStates);
949 return SCARD_E_INVALID_ATR;
953 status = smartcard_pack_locate_cards_return(out, &ret);
954 free(ret.rgReaderStates);
956 if (status != SCARD_S_SUCCESS)
959 return ret.ReturnCode;
962WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsW_Call(scard_call_context* smartcard,
969 WINPR_ASSERT(smartcard);
970 WINPR_ASSERT(operation);
974 ret.ReturnCode = wrap(smartcard, SCardLocateCardsW, operation->hContext, call->mszCards,
975 call->rgReaderStates, call->cReaders);
976 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsW", ret.ReturnCode);
977 ret.rgReaderStates =
nullptr;
979 if (call->cReaders > 0)
984 if (!ret.rgReaderStates)
985 return STATUS_NO_MEMORY;
986 ret.cReaders = call->cReaders;
989 for (UINT32 x = 0; x < ret.cReaders; x++)
994 cur->dwCurrentState = cstate->dwCurrentState;
995 cur->dwEventState = cstate->dwEventState;
996 cur->cbAtr = cstate->cbAtr;
997 CopyMemory(&(cur->rgbAtr), &(cstate->rgbAtr),
sizeof(cur->rgbAtr));
998 if (!smartcard_reader_state_return_is_valid(x, cur))
1000 free(ret.rgReaderStates);
1001 return SCARD_E_INVALID_ATR;
1005 status = smartcard_pack_locate_cards_return(out, &ret);
1006 free(ret.rgReaderStates);
1008 if (status != SCARD_S_SUCCESS)
1011 return ret.ReturnCode;
1014WINPR_ATTR_NODISCARD
static LONG smartcard_ReadCacheA_Call(scard_call_context* smartcard,
1023 WINPR_ASSERT(smartcard);
1025 WINPR_ASSERT(operation);
1027 call = &operation->call.readCacheA;
1028 autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE);
1030 if (!call->Common.fPbDataIsNULL)
1034 ret.pbData = calloc(1, call->Common.cbDataLen);
1036 return SCARD_F_INTERNAL_ERROR;
1038 ret.cbDataLen = call->Common.cbDataLen;
1042 ret.ReturnCode = wrap(smartcard, SCardReadCacheA, operation->hContext,
1043 call->Common.CardIdentifier, call->Common.FreshnessCounter,
1044 call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
1047 wrap(smartcard, SCardReadCacheA, operation->hContext, call->Common.CardIdentifier,
1048 call->Common.FreshnessCounter, call->szLookupName, ret.pbData, &ret.cbDataLen);
1050 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, call->szLookupName,
1053 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
1054 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
1056 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheA", ret.ReturnCode);
1059 status = smartcard_pack_read_cache_return(out, &ret);
1061 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
1064 if (status != SCARD_S_SUCCESS)
1067 return ret.ReturnCode;
1070WINPR_ATTR_NODISCARD
static LONG smartcard_ReadCacheW_Call(scard_call_context* smartcard,
1078 WINPR_ASSERT(smartcard);
1080 WINPR_ASSERT(operation);
1082 call = &operation->call.readCacheW;
1084 if (!call->Common.fPbDataIsNULL)
1085 ret.cbDataLen = SCARD_AUTOALLOCATE;
1088 wrap(smartcard, SCardReadCacheW, operation->hContext, call->Common.CardIdentifier,
1089 call->Common.FreshnessCounter, call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
1091 if (WLog_IsLevelActive(smartcard->log, WLOG_TRACE))
1093 char buffer[128] = WINPR_C_ARRAY_INIT;
1094 (void)ConvertWCharToUtf8(call->szLookupName, buffer,
sizeof(buffer));
1095 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, buffer, ret.cbDataLen);
1097 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
1098 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
1100 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheW", ret.ReturnCode);
1103 status = smartcard_pack_read_cache_return(out, &ret);
1105 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
1107 if (status != SCARD_S_SUCCESS)
1110 return ret.ReturnCode;
1113WINPR_ATTR_NODISCARD
static LONG smartcard_WriteCacheA_Call(scard_call_context* smartcard,
1114 WINPR_ATTR_UNUSED
wStream* out,
1120 WINPR_ASSERT(smartcard);
1122 WINPR_ASSERT(operation);
1124 call = &operation->call.writeCacheA;
1126 ret.ReturnCode = wrap(smartcard, SCardWriteCacheA, operation->hContext,
1127 call->Common.CardIdentifier, call->Common.FreshnessCounter,
1128 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
1129 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheA", ret.ReturnCode);
1130 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheA");
1131 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, call->szLookupName,
1132 call->Common.cbDataLen);
1133 return ret.ReturnCode;
1136WINPR_ATTR_NODISCARD
static LONG smartcard_WriteCacheW_Call(scard_call_context* smartcard,
1137 WINPR_ATTR_UNUSED
wStream* out,
1143 WINPR_ASSERT(smartcard);
1145 WINPR_ASSERT(operation);
1147 call = &operation->call.writeCacheW;
1149 ret.ReturnCode = wrap(smartcard, SCardWriteCacheW, operation->hContext,
1150 call->Common.CardIdentifier, call->Common.FreshnessCounter,
1151 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
1152 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheW", ret.ReturnCode);
1153 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheW");
1155 if (WLog_IsLevelActive(smartcard->log, WLOG_TRACE))
1157 char buffer[128] = WINPR_C_ARRAY_INIT;
1158 (void)ConvertWCharToUtf8(call->szLookupName, buffer,
sizeof(buffer));
1159 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, buffer,
1160 call->Common.cbDataLen);
1162 return ret.ReturnCode;
1165WINPR_ATTR_NODISCARD
static LONG smartcard_GetTransmitCount_Call(scard_call_context* smartcard,
1172 WINPR_ASSERT(smartcard);
1174 WINPR_ASSERT(operation);
1176 ret.ReturnCode = wrap(smartcard, SCardGetTransmitCount, operation->hCard, &ret.cTransmitCount);
1177 scard_log_status_error_wlog(smartcard->log,
"SCardGetTransmitCount", ret.ReturnCode);
1178 status = smartcard_pack_get_transmit_count_return(out, &ret);
1179 if (status != SCARD_S_SUCCESS)
1182 return ret.ReturnCode;
1185WINPR_ATTR_NODISCARD
static LONG smartcard_ReleaseStartedEvent_Call(scard_call_context* smartcard,
1189 WINPR_UNUSED(smartcard);
1191 WINPR_UNUSED(operation);
1193 WLog_Print(smartcard->log, WLOG_WARN,
1194 "According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
1195 "this is not supported?!?");
1196 return SCARD_E_UNSUPPORTED_FEATURE;
1199WINPR_ATTR_NODISCARD
static LONG smartcard_GetReaderIcon_Call(scard_call_context* smartcard,
1207 WINPR_ASSERT(smartcard);
1209 WINPR_ASSERT(operation);
1211 call = &operation->call.getReaderIcon;
1213 ret.cbDataLen = SCARD_AUTOALLOCATE;
1214 ret.ReturnCode = wrap(smartcard, SCardGetReaderIconW, operation->hContext, call->szReaderName,
1215 (LPBYTE)&ret.pbData, &ret.cbDataLen);
1216 scard_log_status_error_wlog(smartcard->log,
"SCardGetReaderIconW", ret.ReturnCode);
1217 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cbDataLen == SCARD_AUTOALLOCATE))
1218 return SCARD_F_UNKNOWN_ERROR;
1220 status = smartcard_pack_get_reader_icon_return(out, &ret);
1221 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
1222 if (status != SCARD_S_SUCCESS)
1225 return ret.ReturnCode;
1228WINPR_ATTR_NODISCARD
static LONG smartcard_GetDeviceTypeId_Call(scard_call_context* smartcard,
1236 WINPR_ASSERT(smartcard);
1238 WINPR_ASSERT(operation);
1240 call = &operation->call.getDeviceTypeId;
1242 ret.ReturnCode = wrap(smartcard, SCardGetDeviceTypeIdW, operation->hContext, call->szReaderName,
1244 scard_log_status_error_wlog(smartcard->log,
"SCardGetDeviceTypeIdW", ret.ReturnCode);
1246 status = smartcard_pack_device_type_id_return(out, &ret);
1247 if (status != SCARD_S_SUCCESS)
1250 return ret.ReturnCode;
1254static BOOL smartcard_context_was_aborted(scard_call_context* smartcard)
1256 WINPR_ASSERT(smartcard);
1258 HANDLE handles[] = { smartcard->stopEvent, freerdp_abort_event(smartcard->context) };
1259 const DWORD rc = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, 0);
1260 return (rc >= WAIT_OBJECT_0) && (rc <= WAIT_OBJECT_0 + ARRAYSIZE(handles));
1264#define SCARD_STATUS_CHANGE_STEP_MS 1000
1267static DWORD smartcard_status_change_step(DWORD dwTimeOut, DWORD waited)
1269 if (dwTimeOut == INFINITE)
1270 return SCARD_STATUS_CHANGE_STEP_MS;
1271 if (waited >= dwTimeOut)
1273 return MIN(dwTimeOut - waited, SCARD_STATUS_CHANGE_STEP_MS);
1276WINPR_ATTR_NODISCARD
static LONG smartcard_GetStatusChangeA_Call(scard_call_context* smartcard,
1280 LONG status = STATUS_NO_MEMORY;
1281 DWORD dwTimeOut = 0;
1286 WINPR_ASSERT(smartcard);
1288 WINPR_ASSERT(operation);
1290 call = &operation->call.getStatusChangeA;
1291 dwTimeOut = call->dwTimeOut;
1293 if (call->cReaders > 0)
1296 ret.rgReaderStates =
1298 if (!rgReaderStates || !ret.rgReaderStates)
1301 ret.cReaders = call->cReaders;
1304 const UINT64 start = GetTickCount64();
1305 for (DWORD waited = 0;;)
1307 const DWORD step = smartcard_status_change_step(dwTimeOut, waited);
1308 if (call->cReaders > 0)
1309 memcpy(rgReaderStates, call->rgReaderStates,
1312 ret.ReturnCode = wrap_raw(smartcard, SCardGetStatusChangeA, operation->hContext, step,
1313 rgReaderStates, call->cReaders);
1314 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1316 if (dwTimeOut != INFINITE)
1319 waited = (DWORD)MIN(GetTickCount64() - start, dwTimeOut);
1320 if (waited >= dwTimeOut)
1323 if (smartcard_context_was_aborted(smartcard))
1326 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", ret.ReturnCode);
1328 status = SCARD_E_INVALID_ATR;
1329 for (UINT32 index = 0; index < ret.cReaders; index++)
1334 rout->dwCurrentState = cur->dwCurrentState;
1335 rout->dwEventState = cur->dwEventState;
1336 rout->cbAtr = cur->cbAtr;
1337 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1338 if (!smartcard_reader_state_return_is_valid(index, rout))
1342 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1344 free(ret.rgReaderStates);
1345 free(rgReaderStates);
1346 if (status != SCARD_S_SUCCESS)
1348 return ret.ReturnCode;
1351WINPR_ATTR_NODISCARD
static LONG smartcard_GetStatusChangeW_Call(scard_call_context* smartcard,
1355 LONG status = STATUS_NO_MEMORY;
1356 DWORD dwTimeOut = 0;
1360 WINPR_ASSERT(smartcard);
1362 WINPR_ASSERT(operation);
1365 dwTimeOut = call->dwTimeOut;
1367 if (call->cReaders > 0)
1370 ret.rgReaderStates =
1372 if (!rgReaderStates || !ret.rgReaderStates)
1375 ret.cReaders = call->cReaders;
1378 const UINT64 start = GetTickCount64();
1379 for (DWORD waited = 0;;)
1381 const DWORD step = smartcard_status_change_step(dwTimeOut, waited);
1382 if (call->cReaders > 0)
1383 memcpy(rgReaderStates, call->rgReaderStates,
1386 ret.ReturnCode = wrap_raw(smartcard, SCardGetStatusChangeW, operation->hContext, step,
1387 rgReaderStates, call->cReaders);
1388 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1390 if (dwTimeOut != INFINITE)
1393 waited = (DWORD)MIN(GetTickCount64() - start, dwTimeOut);
1394 if (waited >= dwTimeOut)
1397 if (smartcard_context_was_aborted(smartcard))
1400 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeW", ret.ReturnCode);
1402 status = SCARD_E_INVALID_ATR;
1403 for (UINT32 index = 0; index < ret.cReaders; index++)
1408 rout->dwCurrentState = cur->dwCurrentState;
1409 rout->dwEventState = cur->dwEventState;
1410 rout->cbAtr = cur->cbAtr;
1411 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1412 if (!smartcard_reader_state_return_is_valid(index, rout))
1416 status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
1418 free(ret.rgReaderStates);
1419 free(rgReaderStates);
1420 if (status != SCARD_S_SUCCESS)
1422 return ret.ReturnCode;
1425WINPR_ATTR_NODISCARD
static LONG smartcard_Cancel_Call(scard_call_context* smartcard,
1426 WINPR_ATTR_UNUSED
wStream* out,
1431 WINPR_ASSERT(smartcard);
1433 WINPR_ASSERT(operation);
1435 ret.ReturnCode = wrap(smartcard, SCardCancel, operation->hContext);
1436 scard_log_status_error_wlog(smartcard->log,
"SCardCancel", ret.ReturnCode);
1437 smartcard_trace_long_return_int(smartcard->log, &ret,
"Cancel");
1438 return ret.ReturnCode;
1441WINPR_ATTR_NODISCARD
static LONG
1445 SCARDHANDLE hCard = 0;
1449 WINPR_ASSERT(smartcard);
1451 WINPR_ASSERT(operation);
1453 call = &operation->call.connectA;
1455 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1456 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1458 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1461 ret.ReturnCode = wrap(smartcard, SCardConnectA, operation->hContext, (
char*)call->szReader,
1462 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1463 &ret.dwActiveProtocol);
1464 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1465 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1467 status = smartcard_pack_connect_return(out, &ret);
1468 if (status != SCARD_S_SUCCESS)
1471 status = ret.ReturnCode;
1477WINPR_ATTR_NODISCARD
static LONG
1481 SCARDHANDLE hCard = 0;
1485 WINPR_ASSERT(smartcard);
1487 WINPR_ASSERT(operation);
1489 call = &operation->call.connectW;
1491 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1492 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1494 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1497 ret.ReturnCode = wrap(smartcard, SCardConnectW, operation->hContext, (WCHAR*)call->szReader,
1498 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1499 &ret.dwActiveProtocol);
1500 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1501 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1503 status = smartcard_pack_connect_return(out, &ret);
1504 if (status != SCARD_S_SUCCESS)
1507 status = ret.ReturnCode;
1513WINPR_ATTR_NODISCARD
static LONG smartcard_Reconnect_Call(scard_call_context* smartcard,
1521 WINPR_ASSERT(smartcard);
1523 WINPR_ASSERT(operation);
1525 call = &operation->call.reconnect;
1527 wrap(smartcard, SCardReconnect, operation->hCard, call->dwShareMode,
1528 call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
1529 scard_log_status_error_wlog(smartcard->log,
"SCardReconnect", ret.ReturnCode);
1530 status = smartcard_pack_reconnect_return(out, &ret);
1531 if (status != SCARD_S_SUCCESS)
1534 return ret.ReturnCode;
1537WINPR_ATTR_NODISCARD
static LONG smartcard_Disconnect_Call(scard_call_context* smartcard,
1538 WINPR_ATTR_UNUSED
wStream* out,
1544 WINPR_ASSERT(smartcard);
1546 WINPR_ASSERT(operation);
1548 call = &operation->call.hCardAndDisposition;
1550 ret.ReturnCode = wrap(smartcard, SCardDisconnect, operation->hCard, call->dwDisposition);
1551 scard_log_status_error_wlog(smartcard->log,
"SCardDisconnect", ret.ReturnCode);
1552 smartcard_trace_long_return_int(smartcard->log, &ret,
"Disconnect");
1554 return ret.ReturnCode;
1557WINPR_ATTR_NODISCARD
static LONG smartcard_BeginTransaction_Call(scard_call_context* smartcard,
1558 WINPR_ATTR_UNUSED
wStream* out,
1563 WINPR_ASSERT(smartcard);
1565 WINPR_ASSERT(operation);
1567 ret.ReturnCode = wrap(smartcard, SCardBeginTransaction, operation->hCard);
1568 scard_log_status_error_wlog(smartcard->log,
"SCardBeginTransaction", ret.ReturnCode);
1569 smartcard_trace_long_return_int(smartcard->log, &ret,
"BeginTransaction");
1570 return ret.ReturnCode;
1573WINPR_ATTR_NODISCARD
static LONG smartcard_EndTransaction_Call(scard_call_context* smartcard,
1574 WINPR_ATTR_UNUSED
wStream* out,
1580 WINPR_ASSERT(smartcard);
1582 WINPR_ASSERT(operation);
1584 call = &operation->call.hCardAndDisposition;
1586 ret.ReturnCode = wrap(smartcard, SCardEndTransaction, operation->hCard, call->dwDisposition);
1587 scard_log_status_error_wlog(smartcard->log,
"SCardEndTransaction", ret.ReturnCode);
1588 smartcard_trace_long_return_int(smartcard->log, &ret,
"EndTransaction");
1589 return ret.ReturnCode;
1592WINPR_ATTR_NODISCARD
static LONG smartcard_State_Call(scard_call_context* smartcard,
wStream* out,
1598 WINPR_ASSERT(smartcard);
1600 WINPR_ASSERT(operation);
1602 ret.cbAtrLen = SCARD_ATR_LENGTH;
1603 ret.ReturnCode = wrap(smartcard, SCardState, operation->hCard, &ret.dwState, &ret.dwProtocol,
1604 (BYTE*)&ret.rgAtr, &ret.cbAtrLen);
1606 scard_log_status_error_wlog(smartcard->log,
"SCardState", ret.ReturnCode);
1607 status = smartcard_pack_state_return(out, &ret);
1608 if (status != SCARD_S_SUCCESS)
1611 return ret.ReturnCode;
1614WINPR_ATTR_NODISCARD
static LONG smartcard_StatusA_Call(scard_call_context* smartcard,
wStream* out,
1619 DWORD cchReaderLen = 0;
1621 LPSTR mszReaderNames =
nullptr;
1624 WINPR_ASSERT(smartcard);
1626 WINPR_ASSERT(operation);
1628 call = &operation->call.status;
1630 call->cbAtrLen = 32;
1631 cbAtrLen = call->cbAtrLen;
1633 if (call->fmszReaderNamesIsNULL)
1636 cchReaderLen = SCARD_AUTOALLOCATE;
1638 status = ret.ReturnCode =
1639 wrap(smartcard, SCardStatusA, operation->hCard,
1640 call->fmszReaderNamesIsNULL ?
nullptr : (LPSTR)&mszReaderNames, &cchReaderLen,
1641 &ret.dwState, &ret.dwProtocol, cbAtrLen ? (BYTE*)&ret.pbAtr : nullptr, &cbAtrLen);
1643 scard_log_status_error_wlog(smartcard->log,
"SCardStatusA", status);
1644 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchReaderLen == SCARD_AUTOALLOCATE))
1645 return SCARD_F_UNKNOWN_ERROR;
1647 if (status == SCARD_S_SUCCESS)
1649 if (!call->fmszReaderNamesIsNULL)
1650 ret.mszReaderNames = (BYTE*)mszReaderNames;
1652 ret.cBytes = cchReaderLen;
1655 ret.cbAtrLen = cbAtrLen;
1658 status = smartcard_pack_status_return(out, &ret, FALSE);
1661 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1663 if (status != SCARD_S_SUCCESS)
1665 return ret.ReturnCode;
1668WINPR_ATTR_NODISCARD
static LONG smartcard_StatusW_Call(scard_call_context* smartcard,
wStream* out,
1673 LPWSTR mszReaderNames =
nullptr;
1677 WINPR_ASSERT(smartcard);
1679 WINPR_ASSERT(operation);
1681 call = &operation->call.status;
1687 cbAtrLen = call->cbAtrLen = 32;
1689 if (call->fmszReaderNamesIsNULL)
1692 ret.cBytes = SCARD_AUTOALLOCATE;
1694 status = ret.ReturnCode =
1695 wrap(smartcard, SCardStatusW, operation->hCard,
1696 call->fmszReaderNamesIsNULL ?
nullptr : (LPWSTR)&mszReaderNames, &ret.cBytes,
1697 &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
1698 scard_log_status_error_wlog(smartcard->log,
"SCardStatusW", status);
1699 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cBytes == SCARD_AUTOALLOCATE))
1700 return SCARD_F_UNKNOWN_ERROR;
1703 if (status == SCARD_S_SUCCESS)
1705 if (!call->fmszReaderNamesIsNULL)
1706 ret.mszReaderNames = (BYTE*)mszReaderNames;
1708 ret.cbAtrLen = cbAtrLen;
1711 if (ret.cBytes != SCARD_AUTOALLOCATE)
1714 WINPR_ASSERT(ret.cBytes < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
1715 blen =
sizeof(WCHAR) * ret.cBytes;
1716 WINPR_ASSERT(blen <= UINT32_MAX);
1717 ret.cBytes = (UINT32)blen;
1720 status = smartcard_pack_status_return(out, &ret, TRUE);
1721 if (status != SCARD_S_SUCCESS)
1725 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1727 return ret.ReturnCode;
1730WINPR_ATTR_NODISCARD
static LONG
1737 WINPR_ASSERT(smartcard);
1739 WINPR_ASSERT(operation);
1741 call = &operation->call.transmit;
1742 ret.cbRecvLength = 0;
1743 ret.pbRecvBuffer =
nullptr;
1745 if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
1747 if (call->cbRecvLength >= 66560)
1748 call->cbRecvLength = 66560;
1750 const UINT32 cbRecvLength = call->cbRecvLength;
1751 ret.pbRecvBuffer = (BYTE*)calloc(1, cbRecvLength);
1753 if (!ret.pbRecvBuffer)
1754 return STATUS_NO_MEMORY;
1755 ret.cbRecvLength = cbRecvLength;
1758 ret.pioRecvPci = call->pioRecvPci;
1760 wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
1761 call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
1763 scard_log_status_error_wlog(smartcard->log,
"SCardTransmit", ret.ReturnCode);
1765 status = smartcard_pack_transmit_return(out, &ret);
1766 free(ret.pbRecvBuffer);
1768 if (status != SCARD_S_SUCCESS)
1770 return ret.ReturnCode;
1773WINPR_ATTR_NODISCARD
static LONG smartcard_Control_Call(scard_call_context* smartcard,
wStream* out,
1780 WINPR_ASSERT(smartcard);
1782 WINPR_ASSERT(operation);
1784 call = &operation->call.control;
1785 ret.pvOutBuffer = (BYTE*)calloc(1, call->cbOutBufferSize);
1787 if (!ret.pvOutBuffer)
1788 return SCARD_E_NO_MEMORY;
1789 ret.cbOutBufferSize = call->cbOutBufferSize;
1792 wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
1793 call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
1794 scard_log_status_error_wlog(smartcard->log,
"SCardControl", ret.ReturnCode);
1795 status = smartcard_pack_control_return(out, &ret);
1797 free(ret.pvOutBuffer);
1798 if (status != SCARD_S_SUCCESS)
1800 return ret.ReturnCode;
1803WINPR_ATTR_NODISCARD
static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard,
1807 BOOL autoAllocate = FALSE;
1809 DWORD cbAttrLen = 0;
1810 LPBYTE pbAttr =
nullptr;
1814 WINPR_ASSERT(smartcard);
1815 WINPR_ASSERT(operation);
1817 call = &operation->call.getAttrib;
1819 if (!call->fpbAttrIsNULL)
1821 autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE);
1822 cbAttrLen = call->cbAttrLen;
1823 if (cbAttrLen && !autoAllocate)
1825 ret.pbAttr = (BYTE*)calloc(1, cbAttrLen);
1828 return SCARD_E_NO_MEMORY;
1831 pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
1835 wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
1836 scard_log_status_error_wlog(smartcard->log,
"SCardGetAttrib", ret.ReturnCode);
1837 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cbAttrLen == SCARD_AUTOALLOCATE))
1838 return SCARD_F_UNKNOWN_ERROR;
1840 ret.cbAttrLen = cbAttrLen;
1842 status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
1845 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
1851WINPR_ATTR_NODISCARD
static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard,
1852 WINPR_ATTR_UNUSED
wStream* out,
1858 WINPR_ASSERT(smartcard);
1860 WINPR_ASSERT(operation);
1862 call = &operation->call.setAttrib;
1864 ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
1866 scard_log_status_error_wlog(smartcard->log,
"SCardSetAttrib", ret.ReturnCode);
1867 smartcard_trace_long_return_int(smartcard->log, &ret,
"SetAttrib");
1869 return ret.ReturnCode;
1872WINPR_ATTR_NODISCARD
static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard,
1873 WINPR_ATTR_UNUSED
wStream* out,
1876 LONG status = SCARD_S_SUCCESS;
1878 WINPR_ASSERT(smartcard);
1880 WINPR_UNUSED(operation);
1882 if (!smartcard->StartedEvent)
1883 smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
1885 if (!smartcard->StartedEvent)
1886 status = SCARD_E_NO_SERVICE;
1891WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard,
1895 LONG status = SCARD_E_INVALID_HANDLE;
1898 WINPR_ASSERT(smartcard);
1899 WINPR_ASSERT(operation);
1906 return STATUS_NO_MEMORY;
1908 for (UINT32 i = 0; i < call->cReaders; i++)
1913 state->szReader = cstate->szReader;
1914 state->dwCurrentState = cstate->dwCurrentState;
1915 state->dwEventState = cstate->dwEventState;
1916 state->cbAtr = cstate->cbAtr;
1918 if (state->cbAtr >
sizeof(state->rgbAtr))
1920 WLog_WARN(SCARD_TAG,
"[%" PRIu32
"] val->cbAtr=%" PRIu32
", max=%" PRIuz, i,
1921 state->cbAtr,
sizeof(state->rgbAtr));
1924 CopyMemory(&(state->rgbAtr), &(cstate->rgbAtr),
sizeof(cstate->rgbAtr));
1927 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1928 0x000001F4, states, call->cReaders);
1930 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", status);
1931 for (UINT32 i = 0; i < call->cAtrs; i++)
1933 for (UINT32 j = 0; j < call->cReaders; j++)
1936 for (UINT32 k = 0; k < winpr_Data_Get_UINT32(&mask->cbAtr); k++)
1938 if ((mask->rgbAtr[k] & mask->rgbMask[k]) !=
1939 (states[j].rgbAtr[k] & mask->rgbMask[k]))
1944 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1949 ret.rgReaderStates =
nullptr;
1951 if (call->cReaders > 0)
1952 ret.rgReaderStates =
1955 if (!ret.rgReaderStates)
1957 status = STATUS_NO_MEMORY;
1961 ret.cReaders = call->cReaders;
1963 status = SCARD_E_INVALID_ATR;
1964 for (UINT32 i = 0; i < ret.cReaders; i++)
1969 cur->dwCurrentState = state->dwCurrentState;
1970 cur->dwEventState = state->dwEventState;
1971 cur->cbAtr = state->cbAtr;
1972 CopyMemory(&(cur->rgbAtr), &(state->rgbAtr),
sizeof(cur->rgbAtr));
1974 if (!smartcard_reader_state_return_is_valid(i, cur))
1978 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1982 free(ret.rgReaderStates);
1983 if (status != SCARD_S_SUCCESS)
1985 return ret.ReturnCode;
1988WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsByATRW_Call(scard_call_context* smartcard,
1992 LONG status = SCARD_E_INVALID_HANDLE;
1995 WINPR_ASSERT(smartcard);
1996 WINPR_ASSERT(operation);
2003 return STATUS_NO_MEMORY;
2005 for (UINT32 i = 0; i < call->cReaders; i++)
2010 state->szReader = cstate->szReader;
2011 state->dwCurrentState = cstate->dwCurrentState;
2012 state->dwEventState = cstate->dwEventState;
2013 state->cbAtr = cstate->cbAtr;
2015 if (state->cbAtr >
sizeof(state->rgbAtr))
2017 WLog_WARN(SCARD_TAG,
"[%" PRIu32
"] val->cbAtr=%" PRIu32
", max=%" PRIuz, i,
2018 state->cbAtr,
sizeof(state->rgbAtr));
2021 CopyMemory(&(state->rgbAtr), &(cstate->rgbAtr),
sizeof(cstate->rgbAtr));
2024 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
2025 0x000001F4, states, call->cReaders);
2027 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeW", status);
2028 for (UINT32 i = 0; i < call->cAtrs; i++)
2030 for (UINT32 j = 0; j < call->cReaders; j++)
2033 for (UINT32 k = 0; k < winpr_Data_Get_UINT32(&mask->cbAtr); k++)
2035 if ((mask->rgbAtr[k] & mask->rgbMask[k]) !=
2036 (states[j].rgbAtr[k] & mask->rgbMask[k]))
2041 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
2046 ret.rgReaderStates =
nullptr;
2048 if (call->cReaders > 0)
2049 ret.rgReaderStates =
2052 if (!ret.rgReaderStates)
2054 status = STATUS_NO_MEMORY;
2058 ret.cReaders = call->cReaders;
2060 status = SCARD_E_INVALID_ATR;
2061 for (UINT32 i = 0; i < ret.cReaders; i++)
2066 cur->dwCurrentState = state->dwCurrentState;
2067 cur->dwEventState = state->dwEventState;
2068 cur->cbAtr = state->cbAtr;
2069 CopyMemory(&(cur->rgbAtr), &(state->rgbAtr),
sizeof(cur->rgbAtr));
2071 if (!smartcard_reader_state_return_is_valid(i, cur))
2075 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
2079 free(ret.rgReaderStates);
2080 if (status != SCARD_S_SUCCESS)
2082 return ret.ReturnCode;
2085LONG smartcard_irp_device_control_call(scard_call_context* ctx,
wStream* out, NTSTATUS* pIoStatus,
2090 size_t objectBufferLength = 0;
2094 WINPR_ASSERT(pIoStatus);
2095 WINPR_ASSERT(operation);
2097 const UINT32 ioControlCode = operation->ioControlCode;
2105 if (!Stream_EnsureRemainingCapacity(out, 2048ull))
2106 return SCARD_E_NO_MEMORY;
2109 Stream_Write_UINT32(out, 0);
2110 Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH);
2111 Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH);
2112 Stream_Write_UINT32(out, 0);
2114 smartcard_handle_activity_begin(ctx, ioControlCode, operation->hCard);
2117 switch (ioControlCode)
2119 case SCARD_IOCTL_ESTABLISHCONTEXT:
2120 result = smartcard_EstablishContext_Call(ctx, out, operation);
2123 case SCARD_IOCTL_RELEASECONTEXT:
2124 result = smartcard_ReleaseContext_Call(ctx, out, operation);
2127 case SCARD_IOCTL_ISVALIDCONTEXT:
2128 result = smartcard_IsValidContext_Call(ctx, out, operation);
2131 case SCARD_IOCTL_LISTREADERGROUPSA:
2132 result = smartcard_ListReaderGroupsA_Call(ctx, out, operation);
2135 case SCARD_IOCTL_LISTREADERGROUPSW:
2136 result = smartcard_ListReaderGroupsW_Call(ctx, out, operation);
2139 case SCARD_IOCTL_LISTREADERSA:
2140 result = smartcard_ListReadersA_Call(ctx, out, operation);
2143 case SCARD_IOCTL_LISTREADERSW:
2144 result = smartcard_ListReadersW_Call(ctx, out, operation);
2147 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
2148 result = smartcard_IntroduceReaderGroupA_Call(ctx, out, operation);
2151 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
2152 result = smartcard_IntroduceReaderGroupW_Call(ctx, out, operation);
2155 case SCARD_IOCTL_FORGETREADERGROUPA:
2156 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
2159 case SCARD_IOCTL_FORGETREADERGROUPW:
2160 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
2163 case SCARD_IOCTL_INTRODUCEREADERA:
2164 result = smartcard_IntroduceReaderA_Call(ctx, out, operation);
2167 case SCARD_IOCTL_INTRODUCEREADERW:
2168 result = smartcard_IntroduceReaderW_Call(ctx, out, operation);
2171 case SCARD_IOCTL_FORGETREADERA:
2172 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
2175 case SCARD_IOCTL_FORGETREADERW:
2176 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
2179 case SCARD_IOCTL_ADDREADERTOGROUPA:
2180 result = smartcard_AddReaderToGroupA_Call(ctx, out, operation);
2183 case SCARD_IOCTL_ADDREADERTOGROUPW:
2184 result = smartcard_AddReaderToGroupW_Call(ctx, out, operation);
2187 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
2188 result = smartcard_RemoveReaderFromGroupA_Call(ctx, out, operation);
2191 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
2192 result = smartcard_RemoveReaderFromGroupW_Call(ctx, out, operation);
2195 case SCARD_IOCTL_LOCATECARDSA:
2196 result = smartcard_LocateCardsA_Call(ctx, out, operation);
2199 case SCARD_IOCTL_LOCATECARDSW:
2200 result = smartcard_LocateCardsW_Call(ctx, out, operation);
2203 case SCARD_IOCTL_GETSTATUSCHANGEA:
2204 result = smartcard_GetStatusChangeA_Call(ctx, out, operation);
2207 case SCARD_IOCTL_GETSTATUSCHANGEW:
2208 result = smartcard_GetStatusChangeW_Call(ctx, out, operation);
2211 case SCARD_IOCTL_CANCEL:
2212 result = smartcard_Cancel_Call(ctx, out, operation);
2215 case SCARD_IOCTL_CONNECTA:
2216 result = smartcard_ConnectA_Call(ctx, out, operation);
2219 case SCARD_IOCTL_CONNECTW:
2220 result = smartcard_ConnectW_Call(ctx, out, operation);
2223 case SCARD_IOCTL_RECONNECT:
2224 result = smartcard_Reconnect_Call(ctx, out, operation);
2227 case SCARD_IOCTL_DISCONNECT:
2228 result = smartcard_Disconnect_Call(ctx, out, operation);
2231 case SCARD_IOCTL_BEGINTRANSACTION:
2232 result = smartcard_BeginTransaction_Call(ctx, out, operation);
2235 case SCARD_IOCTL_ENDTRANSACTION:
2236 result = smartcard_EndTransaction_Call(ctx, out, operation);
2239 case SCARD_IOCTL_STATE:
2240 result = smartcard_State_Call(ctx, out, operation);
2243 case SCARD_IOCTL_STATUSA:
2244 result = smartcard_StatusA_Call(ctx, out, operation);
2247 case SCARD_IOCTL_STATUSW:
2248 result = smartcard_StatusW_Call(ctx, out, operation);
2251 case SCARD_IOCTL_TRANSMIT:
2252 result = smartcard_Transmit_Call(ctx, out, operation);
2255 case SCARD_IOCTL_CONTROL:
2256 result = smartcard_Control_Call(ctx, out, operation);
2259 case SCARD_IOCTL_GETATTRIB:
2260 result = smartcard_GetAttrib_Call(ctx, out, operation);
2263 case SCARD_IOCTL_SETATTRIB:
2264 result = smartcard_SetAttrib_Call(ctx, out, operation);
2267 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
2268 result = smartcard_AccessStartedEvent_Call(ctx, out, operation);
2271 case SCARD_IOCTL_LOCATECARDSBYATRA:
2272 result = smartcard_LocateCardsByATRA_Call(ctx, out, operation);
2275 case SCARD_IOCTL_LOCATECARDSBYATRW:
2276 result = smartcard_LocateCardsByATRW_Call(ctx, out, operation);
2279 case SCARD_IOCTL_READCACHEA:
2280 result = smartcard_ReadCacheA_Call(ctx, out, operation);
2283 case SCARD_IOCTL_READCACHEW:
2284 result = smartcard_ReadCacheW_Call(ctx, out, operation);
2287 case SCARD_IOCTL_WRITECACHEA:
2288 result = smartcard_WriteCacheA_Call(ctx, out, operation);
2291 case SCARD_IOCTL_WRITECACHEW:
2292 result = smartcard_WriteCacheW_Call(ctx, out, operation);
2295 case SCARD_IOCTL_GETTRANSMITCOUNT:
2296 result = smartcard_GetTransmitCount_Call(ctx, out, operation);
2299 case SCARD_IOCTL_RELEASETARTEDEVENT:
2300 result = smartcard_ReleaseStartedEvent_Call(ctx, out, operation);
2303 case SCARD_IOCTL_GETREADERICON:
2304 result = smartcard_GetReaderIcon_Call(ctx, out, operation);
2307 case SCARD_IOCTL_GETDEVICETYPEID:
2308 result = smartcard_GetDeviceTypeId_Call(ctx, out, operation);
2312 result = STATUS_UNSUCCESSFUL;
2316 if (smartcard_handle_activity_end(ctx, ioControlCode, operation->hCard, result))
2318 WLog_Print(ctx->log, WLOG_WARN,
2319 "transaction on hCard 0x%08" PRIxz
2320 " granted after the server ended it, releasing it",
2321 (
size_t)operation->hCard);
2322 const LONG rc = wrap(ctx, SCardEndTransaction, operation->hCard, SCARD_LEAVE_CARD);
2323 scard_log_status_error_wlog(ctx->log,
"SCardEndTransaction", rc);
2324 result = SCARD_E_CANCELLED;
2333 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
2334 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
2336 offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
2337 const LONG rc = smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
2338 if (rc != SCARD_S_SUCCESS)
2342 if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
2343 (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
2344 (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
2346 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
2347 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
2350 *pIoStatus = STATUS_SUCCESS;
2352 if ((result & 0xC0000000L) == 0xC0000000L)
2355 *pIoStatus = result;
2357 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
2358 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
2361 Stream_SealLength(out);
2362 size_t outputBufferLength = Stream_Length(out);
2363 size_t dataEndPos = outputBufferLength;
2365 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
2366 outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
2367 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
2368 objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
2369 WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
2370 WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
2371 if (!Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH))
2372 return SCARD_E_BAD_SEEK;
2381 if (outputBufferLength > operation->outputBufferLength)
2383 WLog_Print(ctx->log, WLOG_DEBUG,
2384 "IRP warn: expected outputBufferLength %" PRIuz
", but current limit %" PRIu32
2385 ", respond with STATUS_BUFFER_TOO_SMALL for retransmit with larger buffer",
2386 outputBufferLength, operation->outputBufferLength);
2388 *pIoStatus = STATUS_BUFFER_TOO_SMALL;
2389 result = *pIoStatus;
2390 outputBufferLength = 0;
2391 objectBufferLength = 0;
2395 WLog_Print(ctx->log, WLOG_TRACE,
"IRP trace: outputBufferLength %" PRIuz
", limit %" PRIu32,
2396 outputBufferLength, operation->outputBufferLength);
2400 Stream_Write_UINT32(out, (UINT32)outputBufferLength);
2401 smartcard_pack_common_type_header(out);
2402 smartcard_pack_private_type_header(
2403 out, (UINT32)objectBufferLength);
2404 Stream_Write_INT32(out, result);
2405 if (result == STATUS_BUFFER_TOO_SMALL)
2406 Stream_SealLength(out);
2407 else if (!Stream_SetPosition(out, dataEndPos))
2408 return SCARD_E_BAD_SEEK;
2409 return SCARD_S_SUCCESS;
2412void context_free(
void* arg)
2414 struct s_scard_context_element* element = arg;
2418 if (element->fn_free)
2419 element->fn_free(element->context);
2423#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
2424scard_call_context* smartcard_call_context_new(
const rdpSettings* settings)
2427 if (!inst || !inst->context)
2429 return smartcard_call_context_new_with_context(inst->context);
2433scard_call_context* smartcard_call_context_new_with_context(rdpContext* context)
2435 WINPR_ASSERT(context);
2436 scard_call_context* ctx = calloc(1,
sizeof(scard_call_context));
2440 ctx->context = context;
2442 const rdpSettings* settings = context->settings;
2443 WINPR_ASSERT(settings);
2445 ctx->log = WLog_Get(SCARD_TAG);
2446 WINPR_ASSERT(ctx->log);
2448 ctx->stopEvent = CreateEventA(
nullptr, TRUE, FALSE,
nullptr);
2449 if (!ctx->stopEvent)
2452 ctx->names = LinkedList_New();
2456#if defined(WITH_SMARTCARD_EMULATE)
2460 if (ctx->useEmulatedCard)
2462#if defined(WITH_SMARTCARD_EMULATE)
2463 ctx->emulation = Emulate_New(settings);
2464 if (!ctx->emulation)
2467 WLog_Print(ctx->log, WLOG_ERROR,
"Smartcard emulation requested, but not supported!");
2476 ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
2478 if (!ctx->hWinSCardLibrary)
2480 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard library: '%s'",
2485 if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
2487 ctx->pWinSCardApi = &ctx->WinSCardApi;
2491 ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
2494 if (!ctx->pWinSCardApi)
2496 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard API!");
2501 ctx->rgSCardContextList = HashTable_New(FALSE);
2502 if (!ctx->rgSCardContextList)
2506 wObject* obj = HashTable_ValueObject(ctx->rgSCardContextList);
2511 if (!smartcard_transaction_watchdog_start(ctx))
2513 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to start idle transaction watchdog!");
2519 WINPR_PRAGMA_DIAG_PUSH
2520 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2521 smartcard_call_context_free(ctx);
2522 WINPR_PRAGMA_DIAG_POP
2526void smartcard_call_context_free(scard_call_context* ctx)
2531 smartcard_call_context_signal_stop(ctx, FALSE);
2534 smartcard_transaction_watchdog_stop(ctx);
2536 LinkedList_Free(ctx->names);
2537 if (ctx->StartedEvent)
2539 WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
2540 wrap_raw(ctx, SCardReleaseStartedEvent);
2543 if (ctx->useEmulatedCard)
2545#ifdef WITH_SMARTCARD_EMULATE
2548 Emulate_Free(ctx->emulation);
2549 ctx->emulation =
nullptr;
2554 if (ctx->hWinSCardLibrary)
2557 FreeLibrary(ctx->hWinSCardLibrary);
2558 ctx->hWinSCardLibrary =
nullptr;
2561 ctx->pWinSCardApi =
nullptr;
2563 HashTable_Free(ctx->rgSCardContextList);
2564 HashTable_Free(ctx->handleStates);
2565 (void)CloseHandle(ctx->stopEvent);
2569BOOL smartcard_call_context_add(scard_call_context* ctx,
const char* name)
2573 return LinkedList_AddLast(ctx->names, name);
2576BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2579 if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
2581 wrap(ctx, SCardCancel, hContext);
2586BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2589 wrap(ctx, SCardReleaseContext, hContext);
2593BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
2598 HashTable_Clear(ctx->rgSCardContextList);
2602BOOL smarcard_call_set_callbacks(scard_call_context* ctx,
void* userdata,
2603 void* (*fn_new)(
void*, SCARDCONTEXT),
void (*fn_free)(
void*))
2606 ctx->userdata = userdata;
2607 ctx->fn_new = fn_new;
2608 ctx->fn_free = fn_free;
2612void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2614 struct s_scard_context_element* element =
nullptr;
2617 element = HashTable_GetItemValue(ctx->rgSCardContextList, (
void*)hContext);
2620 return element->context;
2623BOOL smartcard_call_is_configured(scard_call_context* ctx)
2627#if defined(WITH_SMARTCARD_EMULATE)
2628 if (ctx->useEmulatedCard)
2629 return Emulate_IsConfigured(ctx->emulation);
2635static BOOL smartcard_cancel_context_wait(
const void* key, WINPR_ATTR_UNUSED
void* value,
void* arg)
2637 scard_call_context* ctx = arg;
2640 const LONG rc = wrap_raw(ctx, SCardCancel, (SCARDCONTEXT)key);
2641 if (rc != SCARD_S_SUCCESS)
2642 WLog_Print(ctx->log, WLOG_DEBUG,
"SCardCancel failed with %s", SCardGetErrorString(rc));
2646BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
2650 if (!ctx->stopEvent)
2654 return ResetEvent(ctx->stopEvent);
2656 if (!SetEvent(ctx->stopEvent))
2660 if (ctx->rgSCardContextList && (ctx->useEmulatedCard || ctx->pWinSCardApi))
2661 return HashTable_Foreach(ctx->rgSCardContextList, smartcard_cancel_context_wait, ctx);
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