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;
514 if (status != SCARD_S_SUCCESS)
517 ret.msz = (BYTE*)mszGroups;
519 WINPR_ASSERT(cchGroups < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
520 const size_t blen =
sizeof(WCHAR) * cchGroups;
521 WINPR_ASSERT(blen <= UINT32_MAX);
522 ret.cBytes = (UINT32)blen;
524 status = smartcard_pack_list_reader_groups_return(out, &ret, TRUE);
526 if (status != SCARD_S_SUCCESS)
530 wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
532 return ret.ReturnCode;
536static BOOL filter_match(wLinkedList* list, LPCSTR reader,
size_t readerLen)
541 LinkedList_Enumerator_Reset(list);
543 while (LinkedList_Enumerator_MoveNext(list))
545 const char* filter = LinkedList_Enumerator_Current(list);
549 if (strstr(reader, filter) !=
nullptr)
558static DWORD filter_device_by_name_a(wLinkedList* list, LPSTR* mszReaders, DWORD cchReaders)
563 if (*mszReaders ==
nullptr || LinkedList_Count(list) < 1)
568 LPCSTR rreader = &(*mszReaders)[rpos];
569 LPSTR wreader = &(*mszReaders)[wpos];
570 size_t readerLen = strnlen(rreader, cchReaders - rpos);
572 rpos += readerLen + 1;
574 if (filter_match(list, rreader, readerLen))
576 if (rreader != wreader)
577 memmove(wreader, rreader, readerLen + 1);
579 wpos += readerLen + 1;
581 }
while (rpos < cchReaders);
586 if (wpos >= cchReaders)
589 (*mszReaders)[wpos++] =
'\0';
596static DWORD filter_device_by_name_w(wLinkedList* list, LPWSTR* mszReaders, DWORD cchReaders)
599 LPSTR readers =
nullptr;
601 if (LinkedList_Count(list) < 1)
604 readers = ConvertMszWCharNToUtf8Alloc(*mszReaders, cchReaders,
nullptr);
612 *mszReaders =
nullptr;
613 rc = filter_device_by_name_a(list, &readers, cchReaders);
615 *mszReaders = ConvertMszUtf8NToWCharAlloc(readers, rc,
nullptr);
623WINPR_ATTR_NODISCARD
static LONG smartcard_ListReadersA_Call(scard_call_context* smartcard,
628 LPSTR mszReaders =
nullptr;
630 WINPR_ASSERT(smartcard);
632 WINPR_ASSERT(operation);
635 DWORD cchReaders = SCARD_AUTOALLOCATE;
636 LONG status = ret.ReturnCode = wrap(smartcard, SCardListReadersA, operation->hContext,
637 (LPCSTR)call->mszGroups, (LPSTR)&mszReaders, &cchReaders);
638 if (status == SCARD_S_SUCCESS)
640 if (cchReaders == SCARD_AUTOALLOCATE)
641 status = SCARD_F_UNKNOWN_ERROR;
644 if (status != SCARD_S_SUCCESS)
646 (void)scard_log_status_error_wlog(smartcard->log,
"SCardListReadersA", status);
647 return smartcard_pack_list_readers_return(out, &ret, FALSE);
650 void* original = mszReaders;
651 cchReaders = filter_device_by_name_a(smartcard->names, &mszReaders, cchReaders);
652 ret.msz = (BYTE*)mszReaders;
653 ret.cBytes = cchReaders;
655 status = smartcard_pack_list_readers_return(out, &ret, FALSE);
657 wrap(smartcard, SCardFreeMemory, operation->hContext, original);
659 if (status != SCARD_S_SUCCESS)
660 return scard_log_status_error_wlog(smartcard->log,
"smartcard_pack_list_readers_return",
663 return ret.ReturnCode;
666WINPR_ATTR_NODISCARD
static LONG smartcard_ListReadersW_Call(scard_call_context* smartcard,
672 DWORD cchReaders = 0;
688 WINPR_ASSERT(smartcard);
689 WINPR_ASSERT(operation);
691 call = &operation->call.listReaders;
693 string.bp = call->mszGroups;
694 cchReaders = SCARD_AUTOALLOCATE;
695 status = ret.ReturnCode = wrap(smartcard, SCardListReadersW, operation->hContext,
string.wz,
696 (LPWSTR)&mszReaders.pw, &cchReaders);
697 if (status == SCARD_S_SUCCESS)
699 if (cchReaders == SCARD_AUTOALLOCATE)
700 status = SCARD_F_UNKNOWN_ERROR;
703 if (status != SCARD_S_SUCCESS)
705 (void)scard_log_status_error_wlog(smartcard->log,
"SCardListReadersW", status);
706 return smartcard_pack_list_readers_return(out, &ret, TRUE);
709 void* original = mszReaders.pb;
710 cchReaders = filter_device_by_name_w(smartcard->names, &mszReaders.pw, cchReaders);
711 ret.msz = mszReaders.pb;
712 ret.cBytes = cchReaders *
sizeof(WCHAR);
713 status = smartcard_pack_list_readers_return(out, &ret, TRUE);
716 wrap(smartcard, SCardFreeMemory, operation->hContext, original);
718 if (status != SCARD_S_SUCCESS)
721 return ret.ReturnCode;
724WINPR_ATTR_NODISCARD
static LONG
725smartcard_IntroduceReaderGroupA_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
731 WINPR_ASSERT(smartcard);
733 WINPR_ASSERT(operation);
735 call = &operation->call.contextAndStringA;
736 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupA, operation->hContext, call->sz);
737 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderGroupA", ret.ReturnCode);
738 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderGroupA");
739 return ret.ReturnCode;
742WINPR_ATTR_NODISCARD
static LONG
743smartcard_IntroduceReaderGroupW_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
749 WINPR_ASSERT(smartcard);
751 WINPR_ASSERT(operation);
753 call = &operation->call.contextAndStringW;
754 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupW, operation->hContext, call->sz);
755 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderGroupW", ret.ReturnCode);
756 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderGroupW");
757 return ret.ReturnCode;
760WINPR_ATTR_NODISCARD
static LONG smartcard_IntroduceReaderA_Call(scard_call_context* smartcard,
761 WINPR_ATTR_UNUSED
wStream* out,
767 WINPR_ASSERT(smartcard);
769 WINPR_ASSERT(operation);
771 call = &operation->call.contextAndTwoStringA;
773 wrap(smartcard, SCardIntroduceReaderA, operation->hContext, call->sz1, call->sz2);
774 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderA", ret.ReturnCode);
775 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderA");
776 return ret.ReturnCode;
779WINPR_ATTR_NODISCARD
static LONG smartcard_IntroduceReaderW_Call(scard_call_context* smartcard,
780 WINPR_ATTR_UNUSED
wStream* out,
786 WINPR_ASSERT(smartcard);
788 WINPR_ASSERT(operation);
790 call = &operation->call.contextAndTwoStringW;
792 wrap(smartcard, SCardIntroduceReaderW, operation->hContext, call->sz1, call->sz2);
793 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderW", ret.ReturnCode);
794 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderW");
795 return ret.ReturnCode;
798WINPR_ATTR_NODISCARD
static LONG smartcard_ForgetReaderA_Call(scard_call_context* smartcard,
799 WINPR_ATTR_UNUSED
wStream* out,
805 WINPR_ASSERT(smartcard);
807 WINPR_ASSERT(operation);
809 call = &operation->call.contextAndStringA;
810 ret.ReturnCode = wrap(smartcard, SCardForgetReaderA, operation->hContext, call->sz);
811 scard_log_status_error_wlog(smartcard->log,
"SCardForgetReaderA", ret.ReturnCode);
812 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardForgetReaderA");
813 return ret.ReturnCode;
816WINPR_ATTR_NODISCARD
static LONG smartcard_ForgetReaderW_Call(scard_call_context* smartcard,
817 WINPR_ATTR_UNUSED
wStream* out,
823 WINPR_ASSERT(smartcard);
825 WINPR_ASSERT(operation);
827 call = &operation->call.contextAndStringW;
828 ret.ReturnCode = wrap(smartcard, SCardForgetReaderW, operation->hContext, call->sz);
829 scard_log_status_error_wlog(smartcard->log,
"SCardForgetReaderW", ret.ReturnCode);
830 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardForgetReaderW");
831 return ret.ReturnCode;
834WINPR_ATTR_NODISCARD
static LONG smartcard_AddReaderToGroupA_Call(scard_call_context* smartcard,
835 WINPR_ATTR_UNUSED
wStream* out,
841 WINPR_ASSERT(smartcard);
843 WINPR_ASSERT(operation);
845 call = &operation->call.contextAndTwoStringA;
847 wrap(smartcard, SCardAddReaderToGroupA, operation->hContext, call->sz1, call->sz2);
848 scard_log_status_error_wlog(smartcard->log,
"SCardAddReaderToGroupA", ret.ReturnCode);
849 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardAddReaderToGroupA");
850 return ret.ReturnCode;
853WINPR_ATTR_NODISCARD
static LONG smartcard_AddReaderToGroupW_Call(scard_call_context* smartcard,
854 WINPR_ATTR_UNUSED
wStream* out,
860 WINPR_ASSERT(smartcard);
862 WINPR_ASSERT(operation);
864 call = &operation->call.contextAndTwoStringW;
866 wrap(smartcard, SCardAddReaderToGroupW, operation->hContext, call->sz1, call->sz2);
867 scard_log_status_error_wlog(smartcard->log,
"SCardAddReaderToGroupW", ret.ReturnCode);
868 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardAddReaderToGroupA");
869 return ret.ReturnCode;
872WINPR_ATTR_NODISCARD
static LONG
873smartcard_RemoveReaderFromGroupA_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
879 WINPR_ASSERT(smartcard);
881 WINPR_ASSERT(operation);
883 call = &operation->call.contextAndTwoStringA;
885 wrap(smartcard, SCardRemoveReaderFromGroupA, operation->hContext, call->sz1, call->sz2);
886 scard_log_status_error_wlog(smartcard->log,
"SCardRemoveReaderFromGroupA", ret.ReturnCode);
887 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardRemoveReaderFromGroupA");
888 return ret.ReturnCode;
891WINPR_ATTR_NODISCARD
static LONG
892smartcard_RemoveReaderFromGroupW_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
898 WINPR_ASSERT(smartcard);
900 WINPR_ASSERT(operation);
902 call = &operation->call.contextAndTwoStringW;
904 wrap(smartcard, SCardRemoveReaderFromGroupW, operation->hContext, call->sz1, call->sz2);
905 scard_log_status_error_wlog(smartcard->log,
"SCardRemoveReaderFromGroupW", ret.ReturnCode);
906 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardRemoveReaderFromGroupW");
907 return ret.ReturnCode;
910WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsA_Call(scard_call_context* smartcard,
918 WINPR_ASSERT(smartcard);
919 WINPR_ASSERT(operation);
921 call = &operation->call.locateCardsA;
923 ret.ReturnCode = wrap(smartcard, SCardLocateCardsA, operation->hContext, call->mszCards,
924 call->rgReaderStates, call->cReaders);
925 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsA", ret.ReturnCode);
926 ret.rgReaderStates =
nullptr;
928 if (call->cReaders > 0)
933 if (!ret.rgReaderStates)
934 return STATUS_NO_MEMORY;
935 ret.cReaders = call->cReaders;
938 for (UINT32 x = 0; x < ret.cReaders; x++)
943 cur->dwCurrentState = cstate->dwCurrentState;
944 cur->dwEventState = cstate->dwEventState;
945 cur->cbAtr = cstate->cbAtr;
946 CopyMemory(&(cur->rgbAtr), &(cstate->rgbAtr),
sizeof(cur->rgbAtr));
947 if (!smartcard_reader_state_return_is_valid(x, cur))
949 free(ret.rgReaderStates);
950 return SCARD_E_INVALID_ATR;
954 status = smartcard_pack_locate_cards_return(out, &ret);
955 free(ret.rgReaderStates);
957 if (status != SCARD_S_SUCCESS)
960 return ret.ReturnCode;
963WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsW_Call(scard_call_context* smartcard,
970 WINPR_ASSERT(smartcard);
971 WINPR_ASSERT(operation);
975 ret.ReturnCode = wrap(smartcard, SCardLocateCardsW, operation->hContext, call->mszCards,
976 call->rgReaderStates, call->cReaders);
977 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsW", ret.ReturnCode);
978 ret.rgReaderStates =
nullptr;
980 if (call->cReaders > 0)
985 if (!ret.rgReaderStates)
986 return STATUS_NO_MEMORY;
987 ret.cReaders = call->cReaders;
990 for (UINT32 x = 0; x < ret.cReaders; x++)
995 cur->dwCurrentState = cstate->dwCurrentState;
996 cur->dwEventState = cstate->dwEventState;
997 cur->cbAtr = cstate->cbAtr;
998 CopyMemory(&(cur->rgbAtr), &(cstate->rgbAtr),
sizeof(cur->rgbAtr));
999 if (!smartcard_reader_state_return_is_valid(x, cur))
1001 free(ret.rgReaderStates);
1002 return SCARD_E_INVALID_ATR;
1006 status = smartcard_pack_locate_cards_return(out, &ret);
1007 free(ret.rgReaderStates);
1009 if (status != SCARD_S_SUCCESS)
1012 return ret.ReturnCode;
1015WINPR_ATTR_NODISCARD
static LONG smartcard_ReadCacheA_Call(scard_call_context* smartcard,
1024 WINPR_ASSERT(smartcard);
1026 WINPR_ASSERT(operation);
1028 call = &operation->call.readCacheA;
1029 autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE);
1031 if (!call->Common.fPbDataIsNULL)
1035 ret.pbData = calloc(1, call->Common.cbDataLen);
1037 return SCARD_F_INTERNAL_ERROR;
1039 ret.cbDataLen = call->Common.cbDataLen;
1043 ret.ReturnCode = wrap(smartcard, SCardReadCacheA, operation->hContext,
1044 call->Common.CardIdentifier, call->Common.FreshnessCounter,
1045 call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
1048 wrap(smartcard, SCardReadCacheA, operation->hContext, call->Common.CardIdentifier,
1049 call->Common.FreshnessCounter, call->szLookupName, ret.pbData, &ret.cbDataLen);
1051 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, call->szLookupName,
1054 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
1055 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
1057 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheA", ret.ReturnCode);
1060 status = smartcard_pack_read_cache_return(out, &ret);
1062 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
1065 if (status != SCARD_S_SUCCESS)
1068 return ret.ReturnCode;
1071WINPR_ATTR_NODISCARD
static LONG smartcard_ReadCacheW_Call(scard_call_context* smartcard,
1079 WINPR_ASSERT(smartcard);
1081 WINPR_ASSERT(operation);
1083 call = &operation->call.readCacheW;
1085 if (!call->Common.fPbDataIsNULL)
1086 ret.cbDataLen = SCARD_AUTOALLOCATE;
1089 wrap(smartcard, SCardReadCacheW, operation->hContext, call->Common.CardIdentifier,
1090 call->Common.FreshnessCounter, call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
1092 if (WLog_IsLevelActive(smartcard->log, WLOG_TRACE))
1094 char buffer[128] = WINPR_C_ARRAY_INIT;
1095 (void)ConvertWCharToUtf8(call->szLookupName, buffer,
sizeof(buffer));
1096 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, buffer, ret.cbDataLen);
1098 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
1099 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
1101 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheW", ret.ReturnCode);
1104 status = smartcard_pack_read_cache_return(out, &ret);
1106 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
1108 if (status != SCARD_S_SUCCESS)
1111 return ret.ReturnCode;
1114WINPR_ATTR_NODISCARD
static LONG smartcard_WriteCacheA_Call(scard_call_context* smartcard,
1115 WINPR_ATTR_UNUSED
wStream* out,
1121 WINPR_ASSERT(smartcard);
1123 WINPR_ASSERT(operation);
1125 call = &operation->call.writeCacheA;
1127 ret.ReturnCode = wrap(smartcard, SCardWriteCacheA, operation->hContext,
1128 call->Common.CardIdentifier, call->Common.FreshnessCounter,
1129 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
1130 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheA", ret.ReturnCode);
1131 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheA");
1132 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, call->szLookupName,
1133 call->Common.cbDataLen);
1134 return ret.ReturnCode;
1137WINPR_ATTR_NODISCARD
static LONG smartcard_WriteCacheW_Call(scard_call_context* smartcard,
1138 WINPR_ATTR_UNUSED
wStream* out,
1144 WINPR_ASSERT(smartcard);
1146 WINPR_ASSERT(operation);
1148 call = &operation->call.writeCacheW;
1150 ret.ReturnCode = wrap(smartcard, SCardWriteCacheW, operation->hContext,
1151 call->Common.CardIdentifier, call->Common.FreshnessCounter,
1152 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
1153 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheW", ret.ReturnCode);
1154 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheW");
1156 if (WLog_IsLevelActive(smartcard->log, WLOG_TRACE))
1158 char buffer[128] = WINPR_C_ARRAY_INIT;
1159 (void)ConvertWCharToUtf8(call->szLookupName, buffer,
sizeof(buffer));
1160 WLog_Print(smartcard->log, WLOG_TRACE,
"key=%s, length=%" PRIu32, buffer,
1161 call->Common.cbDataLen);
1163 return ret.ReturnCode;
1166WINPR_ATTR_NODISCARD
static LONG smartcard_GetTransmitCount_Call(scard_call_context* smartcard,
1173 WINPR_ASSERT(smartcard);
1175 WINPR_ASSERT(operation);
1177 ret.ReturnCode = wrap(smartcard, SCardGetTransmitCount, operation->hCard, &ret.cTransmitCount);
1178 scard_log_status_error_wlog(smartcard->log,
"SCardGetTransmitCount", ret.ReturnCode);
1179 status = smartcard_pack_get_transmit_count_return(out, &ret);
1180 if (status != SCARD_S_SUCCESS)
1183 return ret.ReturnCode;
1186WINPR_ATTR_NODISCARD
static LONG smartcard_ReleaseStartedEvent_Call(scard_call_context* smartcard,
1190 WINPR_UNUSED(smartcard);
1192 WINPR_UNUSED(operation);
1194 WLog_Print(smartcard->log, WLOG_WARN,
1195 "According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
1196 "this is not supported?!?");
1197 return SCARD_E_UNSUPPORTED_FEATURE;
1200WINPR_ATTR_NODISCARD
static LONG smartcard_GetReaderIcon_Call(scard_call_context* smartcard,
1208 WINPR_ASSERT(smartcard);
1210 WINPR_ASSERT(operation);
1212 call = &operation->call.getReaderIcon;
1214 ret.cbDataLen = SCARD_AUTOALLOCATE;
1215 ret.ReturnCode = wrap(smartcard, SCardGetReaderIconW, operation->hContext, call->szReaderName,
1216 (LPBYTE)&ret.pbData, &ret.cbDataLen);
1217 scard_log_status_error_wlog(smartcard->log,
"SCardGetReaderIconW", ret.ReturnCode);
1218 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cbDataLen == SCARD_AUTOALLOCATE))
1219 return SCARD_F_UNKNOWN_ERROR;
1221 status = smartcard_pack_get_reader_icon_return(out, &ret);
1222 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
1223 if (status != SCARD_S_SUCCESS)
1226 return ret.ReturnCode;
1229WINPR_ATTR_NODISCARD
static LONG smartcard_GetDeviceTypeId_Call(scard_call_context* smartcard,
1237 WINPR_ASSERT(smartcard);
1239 WINPR_ASSERT(operation);
1241 call = &operation->call.getDeviceTypeId;
1243 ret.ReturnCode = wrap(smartcard, SCardGetDeviceTypeIdW, operation->hContext, call->szReaderName,
1245 scard_log_status_error_wlog(smartcard->log,
"SCardGetDeviceTypeIdW", ret.ReturnCode);
1247 status = smartcard_pack_device_type_id_return(out, &ret);
1248 if (status != SCARD_S_SUCCESS)
1251 return ret.ReturnCode;
1255static BOOL smartcard_context_was_aborted(scard_call_context* smartcard)
1257 WINPR_ASSERT(smartcard);
1259 HANDLE handles[] = { smartcard->stopEvent, freerdp_abort_event(smartcard->context) };
1260 const DWORD rc = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, 0);
1261 return (rc >= WAIT_OBJECT_0) && (rc <= WAIT_OBJECT_0 + ARRAYSIZE(handles));
1265#define SCARD_STATUS_CHANGE_STEP_MS 1000
1268static DWORD smartcard_status_change_step(DWORD dwTimeOut, DWORD waited)
1270 if (dwTimeOut == INFINITE)
1271 return SCARD_STATUS_CHANGE_STEP_MS;
1272 if (waited >= dwTimeOut)
1274 return MIN(dwTimeOut - waited, SCARD_STATUS_CHANGE_STEP_MS);
1277WINPR_ATTR_NODISCARD
static LONG smartcard_GetStatusChangeA_Call(scard_call_context* smartcard,
1281 LONG status = STATUS_NO_MEMORY;
1282 DWORD dwTimeOut = 0;
1287 WINPR_ASSERT(smartcard);
1289 WINPR_ASSERT(operation);
1291 call = &operation->call.getStatusChangeA;
1292 dwTimeOut = call->dwTimeOut;
1294 if (call->cReaders > 0)
1297 ret.rgReaderStates =
1299 if (!rgReaderStates || !ret.rgReaderStates)
1302 ret.cReaders = call->cReaders;
1305 const UINT64 start = GetTickCount64();
1306 for (DWORD waited = 0;;)
1308 const DWORD step = smartcard_status_change_step(dwTimeOut, waited);
1309 if (call->cReaders > 0)
1310 memcpy(rgReaderStates, call->rgReaderStates,
1313 ret.ReturnCode = wrap_raw(smartcard, SCardGetStatusChangeA, operation->hContext, step,
1314 rgReaderStates, call->cReaders);
1315 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1317 if (dwTimeOut != INFINITE)
1320 waited = (DWORD)MIN(GetTickCount64() - start, dwTimeOut);
1321 if (waited >= dwTimeOut)
1324 if (smartcard_context_was_aborted(smartcard))
1327 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", ret.ReturnCode);
1329 status = SCARD_E_INVALID_ATR;
1330 for (UINT32 index = 0; index < ret.cReaders; index++)
1335 rout->dwCurrentState = cur->dwCurrentState;
1336 rout->dwEventState = cur->dwEventState;
1337 rout->cbAtr = cur->cbAtr;
1338 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1339 if (!smartcard_reader_state_return_is_valid(index, rout))
1343 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1345 free(ret.rgReaderStates);
1346 free(rgReaderStates);
1347 if (status != SCARD_S_SUCCESS)
1349 return ret.ReturnCode;
1352WINPR_ATTR_NODISCARD
static LONG smartcard_GetStatusChangeW_Call(scard_call_context* smartcard,
1356 LONG status = STATUS_NO_MEMORY;
1357 DWORD dwTimeOut = 0;
1361 WINPR_ASSERT(smartcard);
1363 WINPR_ASSERT(operation);
1366 dwTimeOut = call->dwTimeOut;
1368 if (call->cReaders > 0)
1371 ret.rgReaderStates =
1373 if (!rgReaderStates || !ret.rgReaderStates)
1376 ret.cReaders = call->cReaders;
1379 const UINT64 start = GetTickCount64();
1380 for (DWORD waited = 0;;)
1382 const DWORD step = smartcard_status_change_step(dwTimeOut, waited);
1383 if (call->cReaders > 0)
1384 memcpy(rgReaderStates, call->rgReaderStates,
1387 ret.ReturnCode = wrap_raw(smartcard, SCardGetStatusChangeW, operation->hContext, step,
1388 rgReaderStates, call->cReaders);
1389 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1391 if (dwTimeOut != INFINITE)
1394 waited = (DWORD)MIN(GetTickCount64() - start, dwTimeOut);
1395 if (waited >= dwTimeOut)
1398 if (smartcard_context_was_aborted(smartcard))
1401 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeW", ret.ReturnCode);
1403 status = SCARD_E_INVALID_ATR;
1404 for (UINT32 index = 0; index < ret.cReaders; index++)
1409 rout->dwCurrentState = cur->dwCurrentState;
1410 rout->dwEventState = cur->dwEventState;
1411 rout->cbAtr = cur->cbAtr;
1412 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1413 if (!smartcard_reader_state_return_is_valid(index, rout))
1417 status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
1419 free(ret.rgReaderStates);
1420 free(rgReaderStates);
1421 if (status != SCARD_S_SUCCESS)
1423 return ret.ReturnCode;
1426WINPR_ATTR_NODISCARD
static LONG smartcard_Cancel_Call(scard_call_context* smartcard,
1427 WINPR_ATTR_UNUSED
wStream* out,
1432 WINPR_ASSERT(smartcard);
1434 WINPR_ASSERT(operation);
1436 ret.ReturnCode = wrap(smartcard, SCardCancel, operation->hContext);
1437 scard_log_status_error_wlog(smartcard->log,
"SCardCancel", ret.ReturnCode);
1438 smartcard_trace_long_return_int(smartcard->log, &ret,
"Cancel");
1439 return ret.ReturnCode;
1442WINPR_ATTR_NODISCARD
static LONG
1446 SCARDHANDLE hCard = 0;
1450 WINPR_ASSERT(smartcard);
1452 WINPR_ASSERT(operation);
1454 call = &operation->call.connectA;
1456 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1457 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1459 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1462 ret.ReturnCode = wrap(smartcard, SCardConnectA, operation->hContext, (
char*)call->szReader,
1463 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1464 &ret.dwActiveProtocol);
1465 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1466 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1468 status = smartcard_pack_connect_return(out, &ret);
1469 if (status != SCARD_S_SUCCESS)
1472 status = ret.ReturnCode;
1478WINPR_ATTR_NODISCARD
static LONG
1482 SCARDHANDLE hCard = 0;
1486 WINPR_ASSERT(smartcard);
1488 WINPR_ASSERT(operation);
1490 call = &operation->call.connectW;
1492 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1493 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1495 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1498 ret.ReturnCode = wrap(smartcard, SCardConnectW, operation->hContext, (WCHAR*)call->szReader,
1499 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1500 &ret.dwActiveProtocol);
1501 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1502 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1504 status = smartcard_pack_connect_return(out, &ret);
1505 if (status != SCARD_S_SUCCESS)
1508 status = ret.ReturnCode;
1514WINPR_ATTR_NODISCARD
static LONG smartcard_Reconnect_Call(scard_call_context* smartcard,
1522 WINPR_ASSERT(smartcard);
1524 WINPR_ASSERT(operation);
1526 call = &operation->call.reconnect;
1528 wrap(smartcard, SCardReconnect, operation->hCard, call->dwShareMode,
1529 call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
1530 scard_log_status_error_wlog(smartcard->log,
"SCardReconnect", ret.ReturnCode);
1531 status = smartcard_pack_reconnect_return(out, &ret);
1532 if (status != SCARD_S_SUCCESS)
1535 return ret.ReturnCode;
1538WINPR_ATTR_NODISCARD
static LONG smartcard_Disconnect_Call(scard_call_context* smartcard,
1539 WINPR_ATTR_UNUSED
wStream* out,
1545 WINPR_ASSERT(smartcard);
1547 WINPR_ASSERT(operation);
1549 call = &operation->call.hCardAndDisposition;
1551 ret.ReturnCode = wrap(smartcard, SCardDisconnect, operation->hCard, call->dwDisposition);
1552 scard_log_status_error_wlog(smartcard->log,
"SCardDisconnect", ret.ReturnCode);
1553 smartcard_trace_long_return_int(smartcard->log, &ret,
"Disconnect");
1555 return ret.ReturnCode;
1558WINPR_ATTR_NODISCARD
static LONG smartcard_BeginTransaction_Call(scard_call_context* smartcard,
1559 WINPR_ATTR_UNUSED
wStream* out,
1564 WINPR_ASSERT(smartcard);
1566 WINPR_ASSERT(operation);
1568 ret.ReturnCode = wrap(smartcard, SCardBeginTransaction, operation->hCard);
1569 scard_log_status_error_wlog(smartcard->log,
"SCardBeginTransaction", ret.ReturnCode);
1570 smartcard_trace_long_return_int(smartcard->log, &ret,
"BeginTransaction");
1571 return ret.ReturnCode;
1574WINPR_ATTR_NODISCARD
static LONG smartcard_EndTransaction_Call(scard_call_context* smartcard,
1575 WINPR_ATTR_UNUSED
wStream* out,
1581 WINPR_ASSERT(smartcard);
1583 WINPR_ASSERT(operation);
1585 call = &operation->call.hCardAndDisposition;
1587 ret.ReturnCode = wrap(smartcard, SCardEndTransaction, operation->hCard, call->dwDisposition);
1588 scard_log_status_error_wlog(smartcard->log,
"SCardEndTransaction", ret.ReturnCode);
1589 smartcard_trace_long_return_int(smartcard->log, &ret,
"EndTransaction");
1590 return ret.ReturnCode;
1593WINPR_ATTR_NODISCARD
static LONG smartcard_State_Call(scard_call_context* smartcard,
wStream* out,
1599 WINPR_ASSERT(smartcard);
1601 WINPR_ASSERT(operation);
1603 ret.cbAtrLen = SCARD_ATR_LENGTH;
1604 ret.ReturnCode = wrap(smartcard, SCardState, operation->hCard, &ret.dwState, &ret.dwProtocol,
1605 (BYTE*)&ret.rgAtr, &ret.cbAtrLen);
1607 scard_log_status_error_wlog(smartcard->log,
"SCardState", ret.ReturnCode);
1608 status = smartcard_pack_state_return(out, &ret);
1609 if (status != SCARD_S_SUCCESS)
1612 return ret.ReturnCode;
1615WINPR_ATTR_NODISCARD
static LONG smartcard_StatusA_Call(scard_call_context* smartcard,
wStream* out,
1620 DWORD cchReaderLen = 0;
1622 LPSTR mszReaderNames =
nullptr;
1625 WINPR_ASSERT(smartcard);
1627 WINPR_ASSERT(operation);
1629 call = &operation->call.status;
1631 call->cbAtrLen = 32;
1632 cbAtrLen = call->cbAtrLen;
1634 if (call->fmszReaderNamesIsNULL)
1637 cchReaderLen = SCARD_AUTOALLOCATE;
1639 status = ret.ReturnCode =
1640 wrap(smartcard, SCardStatusA, operation->hCard,
1641 call->fmszReaderNamesIsNULL ?
nullptr : (LPSTR)&mszReaderNames, &cchReaderLen,
1642 &ret.dwState, &ret.dwProtocol, cbAtrLen ? (BYTE*)&ret.pbAtr : nullptr, &cbAtrLen);
1644 scard_log_status_error_wlog(smartcard->log,
"SCardStatusA", status);
1645 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchReaderLen == SCARD_AUTOALLOCATE))
1646 return SCARD_F_UNKNOWN_ERROR;
1648 if (status == SCARD_S_SUCCESS)
1650 if (!call->fmszReaderNamesIsNULL)
1651 ret.mszReaderNames = (BYTE*)mszReaderNames;
1653 ret.cBytes = cchReaderLen;
1656 ret.cbAtrLen = cbAtrLen;
1659 status = smartcard_pack_status_return(out, &ret, FALSE);
1662 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1664 if (status != SCARD_S_SUCCESS)
1666 return ret.ReturnCode;
1669WINPR_ATTR_NODISCARD
static LONG smartcard_StatusW_Call(scard_call_context* smartcard,
wStream* out,
1674 LPWSTR mszReaderNames =
nullptr;
1678 WINPR_ASSERT(smartcard);
1680 WINPR_ASSERT(operation);
1682 call = &operation->call.status;
1688 cbAtrLen = call->cbAtrLen = 32;
1690 if (call->fmszReaderNamesIsNULL)
1693 ret.cBytes = SCARD_AUTOALLOCATE;
1695 status = ret.ReturnCode =
1696 wrap(smartcard, SCardStatusW, operation->hCard,
1697 call->fmszReaderNamesIsNULL ?
nullptr : (LPWSTR)&mszReaderNames, &ret.cBytes,
1698 &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
1699 scard_log_status_error_wlog(smartcard->log,
"SCardStatusW", status);
1700 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cBytes == SCARD_AUTOALLOCATE))
1701 return SCARD_F_UNKNOWN_ERROR;
1704 if (status == SCARD_S_SUCCESS)
1706 if (!call->fmszReaderNamesIsNULL)
1707 ret.mszReaderNames = (BYTE*)mszReaderNames;
1709 ret.cbAtrLen = cbAtrLen;
1712 if (ret.cBytes != SCARD_AUTOALLOCATE)
1715 WINPR_ASSERT(ret.cBytes < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
1716 blen =
sizeof(WCHAR) * ret.cBytes;
1717 WINPR_ASSERT(blen <= UINT32_MAX);
1718 ret.cBytes = (UINT32)blen;
1721 status = smartcard_pack_status_return(out, &ret, TRUE);
1722 if (status != SCARD_S_SUCCESS)
1726 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1728 return ret.ReturnCode;
1731WINPR_ATTR_NODISCARD
static LONG
1738 WINPR_ASSERT(smartcard);
1740 WINPR_ASSERT(operation);
1742 call = &operation->call.transmit;
1743 ret.cbRecvLength = 0;
1744 ret.pbRecvBuffer =
nullptr;
1746 if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
1748 if (call->cbRecvLength >= 66560)
1749 call->cbRecvLength = 66560;
1751 const UINT32 cbRecvLength = call->cbRecvLength;
1752 ret.pbRecvBuffer = (BYTE*)calloc(1, cbRecvLength);
1754 if (!ret.pbRecvBuffer)
1755 return STATUS_NO_MEMORY;
1756 ret.cbRecvLength = cbRecvLength;
1759 ret.pioRecvPci = call->pioRecvPci;
1761 wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
1762 call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
1764 scard_log_status_error_wlog(smartcard->log,
"SCardTransmit", ret.ReturnCode);
1766 status = smartcard_pack_transmit_return(out, &ret);
1767 free(ret.pbRecvBuffer);
1769 if (status != SCARD_S_SUCCESS)
1771 return ret.ReturnCode;
1774WINPR_ATTR_NODISCARD
static LONG smartcard_Control_Call(scard_call_context* smartcard,
wStream* out,
1781 WINPR_ASSERT(smartcard);
1783 WINPR_ASSERT(operation);
1785 call = &operation->call.control;
1786 ret.pvOutBuffer = (BYTE*)calloc(1, call->cbOutBufferSize);
1788 if (!ret.pvOutBuffer)
1789 return SCARD_E_NO_MEMORY;
1790 ret.cbOutBufferSize = call->cbOutBufferSize;
1793 wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
1794 call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
1795 scard_log_status_error_wlog(smartcard->log,
"SCardControl", ret.ReturnCode);
1796 status = smartcard_pack_control_return(out, &ret);
1798 free(ret.pvOutBuffer);
1799 if (status != SCARD_S_SUCCESS)
1801 return ret.ReturnCode;
1804WINPR_ATTR_NODISCARD
static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard,
1808 BOOL autoAllocate = FALSE;
1810 DWORD cbAttrLen = 0;
1811 LPBYTE pbAttr =
nullptr;
1815 WINPR_ASSERT(smartcard);
1816 WINPR_ASSERT(operation);
1818 call = &operation->call.getAttrib;
1820 if (!call->fpbAttrIsNULL)
1822 autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE);
1823 cbAttrLen = call->cbAttrLen;
1824 if (cbAttrLen && !autoAllocate)
1826 ret.pbAttr = (BYTE*)calloc(1, cbAttrLen);
1829 return SCARD_E_NO_MEMORY;
1832 pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
1836 wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
1837 scard_log_status_error_wlog(smartcard->log,
"SCardGetAttrib", ret.ReturnCode);
1838 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cbAttrLen == SCARD_AUTOALLOCATE))
1839 return SCARD_F_UNKNOWN_ERROR;
1841 ret.cbAttrLen = cbAttrLen;
1843 status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
1846 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
1852WINPR_ATTR_NODISCARD
static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard,
1853 WINPR_ATTR_UNUSED
wStream* out,
1859 WINPR_ASSERT(smartcard);
1861 WINPR_ASSERT(operation);
1863 call = &operation->call.setAttrib;
1865 ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
1867 scard_log_status_error_wlog(smartcard->log,
"SCardSetAttrib", ret.ReturnCode);
1868 smartcard_trace_long_return_int(smartcard->log, &ret,
"SetAttrib");
1870 return ret.ReturnCode;
1873WINPR_ATTR_NODISCARD
static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard,
1874 WINPR_ATTR_UNUSED
wStream* out,
1877 LONG status = SCARD_S_SUCCESS;
1879 WINPR_ASSERT(smartcard);
1881 WINPR_UNUSED(operation);
1883 if (!smartcard->StartedEvent)
1884 smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
1886 if (!smartcard->StartedEvent)
1887 status = SCARD_E_NO_SERVICE;
1892WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard,
1896 LONG status = SCARD_E_INVALID_HANDLE;
1899 WINPR_ASSERT(smartcard);
1900 WINPR_ASSERT(operation);
1907 return STATUS_NO_MEMORY;
1909 for (UINT32 i = 0; i < call->cReaders; i++)
1914 state->szReader = cstate->szReader;
1915 state->dwCurrentState = cstate->dwCurrentState;
1916 state->dwEventState = cstate->dwEventState;
1917 state->cbAtr = cstate->cbAtr;
1919 if (state->cbAtr >
sizeof(state->rgbAtr))
1921 WLog_WARN(SCARD_TAG,
"[%" PRIu32
"] val->cbAtr=%" PRIu32
", max=%" PRIuz, i,
1922 state->cbAtr,
sizeof(state->rgbAtr));
1925 CopyMemory(&(state->rgbAtr), &(cstate->rgbAtr),
sizeof(cstate->rgbAtr));
1928 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1929 0x000001F4, states, call->cReaders);
1931 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", status);
1932 for (UINT32 i = 0; i < call->cAtrs; i++)
1934 for (UINT32 j = 0; j < call->cReaders; j++)
1937 for (UINT32 k = 0; k < winpr_Data_Get_UINT32(&mask->cbAtr); k++)
1939 if ((mask->rgbAtr[k] & mask->rgbMask[k]) !=
1940 (states[j].rgbAtr[k] & mask->rgbMask[k]))
1945 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1950 ret.rgReaderStates =
nullptr;
1952 if (call->cReaders > 0)
1953 ret.rgReaderStates =
1956 if (!ret.rgReaderStates)
1958 status = STATUS_NO_MEMORY;
1962 ret.cReaders = call->cReaders;
1964 status = SCARD_E_INVALID_ATR;
1965 for (UINT32 i = 0; i < ret.cReaders; i++)
1970 cur->dwCurrentState = state->dwCurrentState;
1971 cur->dwEventState = state->dwEventState;
1972 cur->cbAtr = state->cbAtr;
1973 CopyMemory(&(cur->rgbAtr), &(state->rgbAtr),
sizeof(cur->rgbAtr));
1975 if (!smartcard_reader_state_return_is_valid(i, cur))
1979 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1983 free(ret.rgReaderStates);
1984 if (status != SCARD_S_SUCCESS)
1986 return ret.ReturnCode;
1989WINPR_ATTR_NODISCARD
static LONG smartcard_LocateCardsByATRW_Call(scard_call_context* smartcard,
1993 LONG status = SCARD_E_INVALID_HANDLE;
1996 WINPR_ASSERT(smartcard);
1997 WINPR_ASSERT(operation);
2004 return STATUS_NO_MEMORY;
2006 for (UINT32 i = 0; i < call->cReaders; i++)
2011 state->szReader = cstate->szReader;
2012 state->dwCurrentState = cstate->dwCurrentState;
2013 state->dwEventState = cstate->dwEventState;
2014 state->cbAtr = cstate->cbAtr;
2016 if (state->cbAtr >
sizeof(state->rgbAtr))
2018 WLog_WARN(SCARD_TAG,
"[%" PRIu32
"] val->cbAtr=%" PRIu32
", max=%" PRIuz, i,
2019 state->cbAtr,
sizeof(state->rgbAtr));
2022 CopyMemory(&(state->rgbAtr), &(cstate->rgbAtr),
sizeof(cstate->rgbAtr));
2025 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
2026 0x000001F4, states, call->cReaders);
2028 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeW", status);
2029 for (UINT32 i = 0; i < call->cAtrs; i++)
2031 for (UINT32 j = 0; j < call->cReaders; j++)
2034 for (UINT32 k = 0; k < winpr_Data_Get_UINT32(&mask->cbAtr); k++)
2036 if ((mask->rgbAtr[k] & mask->rgbMask[k]) !=
2037 (states[j].rgbAtr[k] & mask->rgbMask[k]))
2042 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
2047 ret.rgReaderStates =
nullptr;
2049 if (call->cReaders > 0)
2050 ret.rgReaderStates =
2053 if (!ret.rgReaderStates)
2055 status = STATUS_NO_MEMORY;
2059 ret.cReaders = call->cReaders;
2061 status = SCARD_E_INVALID_ATR;
2062 for (UINT32 i = 0; i < ret.cReaders; i++)
2067 cur->dwCurrentState = state->dwCurrentState;
2068 cur->dwEventState = state->dwEventState;
2069 cur->cbAtr = state->cbAtr;
2070 CopyMemory(&(cur->rgbAtr), &(state->rgbAtr),
sizeof(cur->rgbAtr));
2072 if (!smartcard_reader_state_return_is_valid(i, cur))
2076 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
2080 free(ret.rgReaderStates);
2081 if (status != SCARD_S_SUCCESS)
2083 return ret.ReturnCode;
2086LONG smartcard_irp_device_control_call(scard_call_context* ctx,
wStream* out, NTSTATUS* pIoStatus,
2091 size_t objectBufferLength = 0;
2095 WINPR_ASSERT(pIoStatus);
2096 WINPR_ASSERT(operation);
2098 const UINT32 ioControlCode = operation->ioControlCode;
2106 if (!Stream_EnsureRemainingCapacity(out, 2048ull))
2107 return SCARD_E_NO_MEMORY;
2110 Stream_Write_UINT32(out, 0);
2111 Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH);
2112 Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH);
2113 Stream_Write_UINT32(out, 0);
2115 smartcard_handle_activity_begin(ctx, ioControlCode, operation->hCard);
2118 switch (ioControlCode)
2120 case SCARD_IOCTL_ESTABLISHCONTEXT:
2121 result = smartcard_EstablishContext_Call(ctx, out, operation);
2124 case SCARD_IOCTL_RELEASECONTEXT:
2125 result = smartcard_ReleaseContext_Call(ctx, out, operation);
2128 case SCARD_IOCTL_ISVALIDCONTEXT:
2129 result = smartcard_IsValidContext_Call(ctx, out, operation);
2132 case SCARD_IOCTL_LISTREADERGROUPSA:
2133 result = smartcard_ListReaderGroupsA_Call(ctx, out, operation);
2136 case SCARD_IOCTL_LISTREADERGROUPSW:
2137 result = smartcard_ListReaderGroupsW_Call(ctx, out, operation);
2140 case SCARD_IOCTL_LISTREADERSA:
2141 result = smartcard_ListReadersA_Call(ctx, out, operation);
2144 case SCARD_IOCTL_LISTREADERSW:
2145 result = smartcard_ListReadersW_Call(ctx, out, operation);
2148 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
2149 result = smartcard_IntroduceReaderGroupA_Call(ctx, out, operation);
2152 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
2153 result = smartcard_IntroduceReaderGroupW_Call(ctx, out, operation);
2156 case SCARD_IOCTL_FORGETREADERGROUPA:
2157 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
2160 case SCARD_IOCTL_FORGETREADERGROUPW:
2161 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
2164 case SCARD_IOCTL_INTRODUCEREADERA:
2165 result = smartcard_IntroduceReaderA_Call(ctx, out, operation);
2168 case SCARD_IOCTL_INTRODUCEREADERW:
2169 result = smartcard_IntroduceReaderW_Call(ctx, out, operation);
2172 case SCARD_IOCTL_FORGETREADERA:
2173 result = smartcard_ForgetReaderA_Call(ctx, out, operation);
2176 case SCARD_IOCTL_FORGETREADERW:
2177 result = smartcard_ForgetReaderW_Call(ctx, out, operation);
2180 case SCARD_IOCTL_ADDREADERTOGROUPA:
2181 result = smartcard_AddReaderToGroupA_Call(ctx, out, operation);
2184 case SCARD_IOCTL_ADDREADERTOGROUPW:
2185 result = smartcard_AddReaderToGroupW_Call(ctx, out, operation);
2188 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
2189 result = smartcard_RemoveReaderFromGroupA_Call(ctx, out, operation);
2192 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
2193 result = smartcard_RemoveReaderFromGroupW_Call(ctx, out, operation);
2196 case SCARD_IOCTL_LOCATECARDSA:
2197 result = smartcard_LocateCardsA_Call(ctx, out, operation);
2200 case SCARD_IOCTL_LOCATECARDSW:
2201 result = smartcard_LocateCardsW_Call(ctx, out, operation);
2204 case SCARD_IOCTL_GETSTATUSCHANGEA:
2205 result = smartcard_GetStatusChangeA_Call(ctx, out, operation);
2208 case SCARD_IOCTL_GETSTATUSCHANGEW:
2209 result = smartcard_GetStatusChangeW_Call(ctx, out, operation);
2212 case SCARD_IOCTL_CANCEL:
2213 result = smartcard_Cancel_Call(ctx, out, operation);
2216 case SCARD_IOCTL_CONNECTA:
2217 result = smartcard_ConnectA_Call(ctx, out, operation);
2220 case SCARD_IOCTL_CONNECTW:
2221 result = smartcard_ConnectW_Call(ctx, out, operation);
2224 case SCARD_IOCTL_RECONNECT:
2225 result = smartcard_Reconnect_Call(ctx, out, operation);
2228 case SCARD_IOCTL_DISCONNECT:
2229 result = smartcard_Disconnect_Call(ctx, out, operation);
2232 case SCARD_IOCTL_BEGINTRANSACTION:
2233 result = smartcard_BeginTransaction_Call(ctx, out, operation);
2236 case SCARD_IOCTL_ENDTRANSACTION:
2237 result = smartcard_EndTransaction_Call(ctx, out, operation);
2240 case SCARD_IOCTL_STATE:
2241 result = smartcard_State_Call(ctx, out, operation);
2244 case SCARD_IOCTL_STATUSA:
2245 result = smartcard_StatusA_Call(ctx, out, operation);
2248 case SCARD_IOCTL_STATUSW:
2249 result = smartcard_StatusW_Call(ctx, out, operation);
2252 case SCARD_IOCTL_TRANSMIT:
2253 result = smartcard_Transmit_Call(ctx, out, operation);
2256 case SCARD_IOCTL_CONTROL:
2257 result = smartcard_Control_Call(ctx, out, operation);
2260 case SCARD_IOCTL_GETATTRIB:
2261 result = smartcard_GetAttrib_Call(ctx, out, operation);
2264 case SCARD_IOCTL_SETATTRIB:
2265 result = smartcard_SetAttrib_Call(ctx, out, operation);
2268 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
2269 result = smartcard_AccessStartedEvent_Call(ctx, out, operation);
2272 case SCARD_IOCTL_LOCATECARDSBYATRA:
2273 result = smartcard_LocateCardsByATRA_Call(ctx, out, operation);
2276 case SCARD_IOCTL_LOCATECARDSBYATRW:
2277 result = smartcard_LocateCardsByATRW_Call(ctx, out, operation);
2280 case SCARD_IOCTL_READCACHEA:
2281 result = smartcard_ReadCacheA_Call(ctx, out, operation);
2284 case SCARD_IOCTL_READCACHEW:
2285 result = smartcard_ReadCacheW_Call(ctx, out, operation);
2288 case SCARD_IOCTL_WRITECACHEA:
2289 result = smartcard_WriteCacheA_Call(ctx, out, operation);
2292 case SCARD_IOCTL_WRITECACHEW:
2293 result = smartcard_WriteCacheW_Call(ctx, out, operation);
2296 case SCARD_IOCTL_GETTRANSMITCOUNT:
2297 result = smartcard_GetTransmitCount_Call(ctx, out, operation);
2300 case SCARD_IOCTL_RELEASETARTEDEVENT:
2301 result = smartcard_ReleaseStartedEvent_Call(ctx, out, operation);
2304 case SCARD_IOCTL_GETREADERICON:
2305 result = smartcard_GetReaderIcon_Call(ctx, out, operation);
2308 case SCARD_IOCTL_GETDEVICETYPEID:
2309 result = smartcard_GetDeviceTypeId_Call(ctx, out, operation);
2313 result = STATUS_UNSUCCESSFUL;
2317 if (smartcard_handle_activity_end(ctx, ioControlCode, operation->hCard, result))
2319 WLog_Print(ctx->log, WLOG_WARN,
2320 "transaction on hCard 0x%08" PRIxz
2321 " granted after the server ended it, releasing it",
2322 (
size_t)operation->hCard);
2323 const LONG rc = wrap(ctx, SCardEndTransaction, operation->hCard, SCARD_LEAVE_CARD);
2324 scard_log_status_error_wlog(ctx->log,
"SCardEndTransaction", rc);
2325 result = SCARD_E_CANCELLED;
2334 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
2335 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
2337 offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
2338 const LONG rc = smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
2339 if (rc != SCARD_S_SUCCESS)
2343 if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
2344 (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
2345 (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
2347 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
2348 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
2351 *pIoStatus = STATUS_SUCCESS;
2353 if ((result & 0xC0000000L) == 0xC0000000L)
2356 *pIoStatus = result;
2358 scard_log_status_error_wlog(ctx->log,
"IRP failure: %s (0x%08" PRIX32
")", result,
2359 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
2362 Stream_SealLength(out);
2363 size_t outputBufferLength = Stream_Length(out);
2364 size_t dataEndPos = outputBufferLength;
2366 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
2367 outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
2368 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
2369 objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
2370 WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
2371 WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
2372 if (!Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH))
2373 return SCARD_E_BAD_SEEK;
2382 if (outputBufferLength > operation->outputBufferLength)
2384 WLog_Print(ctx->log, WLOG_DEBUG,
2385 "IRP warn: expected outputBufferLength %" PRIuz
", but current limit %" PRIu32
2386 ", respond with STATUS_BUFFER_TOO_SMALL for retransmit with larger buffer",
2387 outputBufferLength, operation->outputBufferLength);
2389 *pIoStatus = STATUS_BUFFER_TOO_SMALL;
2390 result = *pIoStatus;
2391 outputBufferLength = 0;
2392 objectBufferLength = 0;
2396 WLog_Print(ctx->log, WLOG_TRACE,
"IRP trace: outputBufferLength %" PRIuz
", limit %" PRIu32,
2397 outputBufferLength, operation->outputBufferLength);
2401 Stream_Write_UINT32(out, (UINT32)outputBufferLength);
2402 smartcard_pack_common_type_header(out);
2403 smartcard_pack_private_type_header(
2404 out, (UINT32)objectBufferLength);
2405 Stream_Write_INT32(out, result);
2406 if (result == STATUS_BUFFER_TOO_SMALL)
2407 Stream_SealLength(out);
2408 else if (!Stream_SetPosition(out, dataEndPos))
2409 return SCARD_E_BAD_SEEK;
2410 return SCARD_S_SUCCESS;
2413void context_free(
void* arg)
2415 struct s_scard_context_element* element = arg;
2419 if (element->fn_free)
2420 element->fn_free(element->context);
2424#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
2425scard_call_context* smartcard_call_context_new(
const rdpSettings* settings)
2428 if (!inst || !inst->context)
2430 return smartcard_call_context_new_with_context(inst->context);
2434scard_call_context* smartcard_call_context_new_with_context(rdpContext* context)
2436 WINPR_ASSERT(context);
2437 scard_call_context* ctx = calloc(1,
sizeof(scard_call_context));
2441 ctx->context = context;
2443 const rdpSettings* settings = context->settings;
2444 WINPR_ASSERT(settings);
2446 ctx->log = WLog_Get(SCARD_TAG);
2447 WINPR_ASSERT(ctx->log);
2449 ctx->stopEvent = CreateEventA(
nullptr, TRUE, FALSE,
nullptr);
2450 if (!ctx->stopEvent)
2453 ctx->names = LinkedList_New();
2457#if defined(WITH_SMARTCARD_EMULATE)
2461 if (ctx->useEmulatedCard)
2463#if defined(WITH_SMARTCARD_EMULATE)
2464 ctx->emulation = Emulate_New(settings);
2465 if (!ctx->emulation)
2468 WLog_Print(ctx->log, WLOG_ERROR,
"Smartcard emulation requested, but not supported!");
2477 ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
2479 if (!ctx->hWinSCardLibrary)
2481 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard library: '%s'",
2486 if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
2488 ctx->pWinSCardApi = &ctx->WinSCardApi;
2492 ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
2495 if (!ctx->pWinSCardApi)
2497 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard API!");
2502 ctx->rgSCardContextList = HashTable_New(FALSE);
2503 if (!ctx->rgSCardContextList)
2507 wObject* obj = HashTable_ValueObject(ctx->rgSCardContextList);
2512 if (!smartcard_transaction_watchdog_start(ctx))
2514 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to start idle transaction watchdog!");
2520 WINPR_PRAGMA_DIAG_PUSH
2521 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2522 smartcard_call_context_free(ctx);
2523 WINPR_PRAGMA_DIAG_POP
2527void smartcard_call_context_free(scard_call_context* ctx)
2532 smartcard_call_context_signal_stop(ctx, FALSE);
2535 smartcard_transaction_watchdog_stop(ctx);
2537 LinkedList_Free(ctx->names);
2538 if (ctx->StartedEvent)
2540 WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
2541 wrap_raw(ctx, SCardReleaseStartedEvent);
2544 if (ctx->useEmulatedCard)
2546#ifdef WITH_SMARTCARD_EMULATE
2549 Emulate_Free(ctx->emulation);
2550 ctx->emulation =
nullptr;
2555 if (ctx->hWinSCardLibrary)
2558 FreeLibrary(ctx->hWinSCardLibrary);
2559 ctx->hWinSCardLibrary =
nullptr;
2562 ctx->pWinSCardApi =
nullptr;
2564 HashTable_Free(ctx->rgSCardContextList);
2565 HashTable_Free(ctx->handleStates);
2566 (void)CloseHandle(ctx->stopEvent);
2570BOOL smartcard_call_context_add(scard_call_context* ctx,
const char* name)
2574 return LinkedList_AddLast(ctx->names, name);
2577BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2580 if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
2582 wrap(ctx, SCardCancel, hContext);
2587BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2590 wrap(ctx, SCardReleaseContext, hContext);
2594BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
2599 HashTable_Clear(ctx->rgSCardContextList);
2603BOOL smarcard_call_set_callbacks(scard_call_context* ctx,
void* userdata,
2604 void* (*fn_new)(
void*, SCARDCONTEXT),
void (*fn_free)(
void*))
2607 ctx->userdata = userdata;
2608 ctx->fn_new = fn_new;
2609 ctx->fn_free = fn_free;
2613void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2615 struct s_scard_context_element* element =
nullptr;
2618 element = HashTable_GetItemValue(ctx->rgSCardContextList, (
void*)hContext);
2621 return element->context;
2624BOOL smartcard_call_is_configured(scard_call_context* ctx)
2628#if defined(WITH_SMARTCARD_EMULATE)
2629 if (ctx->useEmulatedCard)
2630 return Emulate_IsConfigured(ctx->emulation);
2636static BOOL smartcard_cancel_context_wait(
const void* key, WINPR_ATTR_UNUSED
void* value,
void* arg)
2638 scard_call_context* ctx = arg;
2641 const LONG rc = wrap_raw(ctx, SCardCancel, (SCARDCONTEXT)key);
2642 if (rc != SCARD_S_SUCCESS)
2643 WLog_Print(ctx->log, WLOG_DEBUG,
"SCardCancel failed with %s", SCardGetErrorString(rc));
2647BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
2651 if (!ctx->stopEvent)
2655 return ResetEvent(ctx->stopEvent);
2657 if (!SetEvent(ctx->stopEvent))
2661 if (ctx->rgSCardContextList && (ctx->useEmulatedCard || ctx->pWinSCardApi))
2662 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