26#include <freerdp/config.h>
28#include <winpr/assert.h>
31#include <winpr/print.h>
32#include <winpr/stream.h>
33#include <winpr/library.h>
34#include <winpr/smartcard.h>
36#include <freerdp/freerdp.h>
37#include <freerdp/channels/rdpdr.h>
38#include <freerdp/channels/scard.h>
40#include <freerdp/utils/rdpdr_utils.h>
41#include <freerdp/utils/smartcard_pack.h>
42#include <freerdp/utils/smartcard_call.h>
44#include <freerdp/log.h>
45#define TAG FREERDP_TAG("utils.smartcard.call")
47#if defined(WITH_SMARTCARD_EMULATE)
48#include <freerdp/emulate/scard/smartcard_emulate.h>
50#define wrap(ctx, fkt, ...) \
51 ctx->useEmulatedCard ? Emulate_##fkt(ctx->emulation, ##__VA_ARGS__) \
52 : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
53#define wrap_ptr(ctx, fkt, ...) wrap(ctx, fkt, ##__VA_ARGS__)
55#define wrap(ctx, fkt, ...) \
56 ctx->useEmulatedCard ? SCARD_F_INTERNAL_ERROR : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
57#define wrap_ptr(ctx, fkt, ...) \
58 ctx->useEmulatedCard ? NULL : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
61struct s_scard_call_context
66 wHashTable* rgSCardContextList;
67#if defined(WITH_SMARTCARD_EMULATE)
68 SmartcardEmulationContext* emulation;
70 HANDLE hWinSCardLibrary;
76 void* (*fn_new)(
void*, SCARDCONTEXT);
77 void (*fn_free)(
void*);
80struct s_scard_context_element
83 void (*fn_free)(
void*);
86static void context_free(
void* arg);
88static LONG smartcard_EstablishContext_Call(scard_call_context* smartcard,
wStream* out,
92 SCARDCONTEXT hContext = { 0 };
95 status = ret.ReturnCode =
96 wrap(smartcard, SCardEstablishContext, call->dwScope, NULL, NULL, &hContext);
98 if (ret.ReturnCode == SCARD_S_SUCCESS)
100 const void* key = (
void*)(
size_t)hContext;
101 struct s_scard_context_element* pContext =
102 calloc(1,
sizeof(
struct s_scard_context_element));
104 return STATUS_NO_MEMORY;
106 pContext->fn_free = smartcard->fn_free;
108 if (smartcard->fn_new)
110 pContext->context = smartcard->fn_new(smartcard->userdata, hContext);
111 if (!pContext->context)
114 return STATUS_NO_MEMORY;
118 if (!HashTable_Insert(smartcard->rgSCardContextList, key, (
void*)pContext))
120 WLog_ERR(TAG,
"ListDictionary_Add failed!");
121 context_free(pContext);
122 return STATUS_INTERNAL_ERROR;
127 return scard_log_status_error(TAG,
"SCardEstablishContext", status);
131 smartcard_scard_context_native_to_redir(&(ret.hContext), hContext);
133 status = smartcard_pack_establish_context_return(out, &ret);
134 if (status != SCARD_S_SUCCESS)
136 return scard_log_status_error(TAG,
"smartcard_pack_establish_context_return", status);
139 return ret.ReturnCode;
142static LONG smartcard_ReleaseContext_Call(scard_call_context* smartcard,
143 WINPR_ATTR_UNUSED
wStream* out,
148 WINPR_ASSERT(smartcard);
150 WINPR_ASSERT(operation);
152 ret.ReturnCode = wrap(smartcard, SCardReleaseContext, operation->hContext);
154 if (ret.ReturnCode == SCARD_S_SUCCESS)
155 HashTable_Remove(smartcard->rgSCardContextList, (
void*)operation->hContext);
158 return scard_log_status_error(TAG,
"SCardReleaseContext", ret.ReturnCode);
161 smartcard_trace_long_return(&ret,
"ReleaseContext");
162 return ret.ReturnCode;
165static LONG smartcard_IsValidContext_Call(scard_call_context* smartcard,
166 WINPR_ATTR_UNUSED
wStream* out,
171 WINPR_ASSERT(smartcard);
173 WINPR_ASSERT(operation);
175 ret.ReturnCode = wrap(smartcard, SCardIsValidContext, operation->hContext);
176 smartcard_trace_long_return(&ret,
"IsValidContext");
177 return ret.ReturnCode;
180static LONG smartcard_ListReaderGroupsA_Call(scard_call_context* smartcard,
wStream* out,
185 LPSTR mszGroups = NULL;
188 WINPR_ASSERT(smartcard);
190 WINPR_ASSERT(operation);
192 cchGroups = SCARD_AUTOALLOCATE;
194 wrap(smartcard, SCardListReaderGroupsA, operation->hContext, (LPSTR)&mszGroups, &cchGroups);
195 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchGroups == SCARD_AUTOALLOCATE))
196 return SCARD_F_UNKNOWN_ERROR;
198 ret.msz = (BYTE*)mszGroups;
199 ret.cBytes = cchGroups;
201 status = smartcard_pack_list_reader_groups_return(out, &ret, FALSE);
203 if (status != SCARD_S_SUCCESS)
207 wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
209 return ret.ReturnCode;
212static LONG smartcard_ListReaderGroupsW_Call(scard_call_context* smartcard,
wStream* out,
217 LPWSTR mszGroups = NULL;
220 WINPR_ASSERT(smartcard);
222 WINPR_ASSERT(operation);
224 cchGroups = SCARD_AUTOALLOCATE;
225 status = ret.ReturnCode = wrap(smartcard, SCardListReaderGroupsW, operation->hContext,
226 (LPWSTR)&mszGroups, &cchGroups);
227 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchGroups == SCARD_AUTOALLOCATE))
228 return SCARD_F_UNKNOWN_ERROR;
230 ret.msz = (BYTE*)mszGroups;
232 WINPR_ASSERT(cchGroups < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
233 const size_t blen =
sizeof(WCHAR) * cchGroups;
234 WINPR_ASSERT(blen <= UINT32_MAX);
235 ret.cBytes = (UINT32)blen;
237 if (status != SCARD_S_SUCCESS)
240 status = smartcard_pack_list_reader_groups_return(out, &ret, TRUE);
242 if (status != SCARD_S_SUCCESS)
246 wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
248 return ret.ReturnCode;
251static BOOL filter_match(wLinkedList* list, LPCSTR reader,
size_t readerLen)
256 LinkedList_Enumerator_Reset(list);
258 while (LinkedList_Enumerator_MoveNext(list))
260 const char* filter = LinkedList_Enumerator_Current(list);
264 if (strstr(reader, filter) != NULL)
272static DWORD filter_device_by_name_a(wLinkedList* list, LPSTR* mszReaders, DWORD cchReaders)
277 if (*mszReaders == NULL || LinkedList_Count(list) < 1)
282 LPCSTR rreader = &(*mszReaders)[rpos];
283 LPSTR wreader = &(*mszReaders)[wpos];
284 size_t readerLen = strnlen(rreader, cchReaders - rpos);
286 rpos += readerLen + 1;
288 if (filter_match(list, rreader, readerLen))
290 if (rreader != wreader)
291 memmove(wreader, rreader, readerLen + 1);
293 wpos += readerLen + 1;
295 }
while (rpos < cchReaders);
300 if (wpos >= cchReaders)
303 (*mszReaders)[wpos++] =
'\0';
309static DWORD filter_device_by_name_w(wLinkedList* list, LPWSTR* mszReaders, DWORD cchReaders)
312 LPSTR readers = NULL;
314 if (LinkedList_Count(list) < 1)
317 readers = ConvertMszWCharNToUtf8Alloc(*mszReaders, cchReaders, NULL);
327 rc = filter_device_by_name_a(list, &readers, cchReaders);
329 *mszReaders = ConvertMszUtf8NToWCharAlloc(readers, rc, NULL);
337static LONG smartcard_ListReadersA_Call(scard_call_context* smartcard,
wStream* out,
341 LPSTR mszReaders = NULL;
343 WINPR_ASSERT(smartcard);
345 WINPR_ASSERT(operation);
348 DWORD cchReaders = SCARD_AUTOALLOCATE;
349 LONG status = ret.ReturnCode = wrap(smartcard, SCardListReadersA, operation->hContext,
350 (LPCSTR)call->mszGroups, (LPSTR)&mszReaders, &cchReaders);
351 if (status == SCARD_S_SUCCESS)
353 if (cchReaders == SCARD_AUTOALLOCATE)
354 status = SCARD_F_UNKNOWN_ERROR;
357 if (status != SCARD_S_SUCCESS)
359 (void)scard_log_status_error(TAG,
"SCardListReadersA", status);
360 return smartcard_pack_list_readers_return(out, &ret, FALSE);
363 cchReaders = filter_device_by_name_a(smartcard->names, &mszReaders, cchReaders);
364 ret.msz = (BYTE*)mszReaders;
365 ret.cBytes = cchReaders;
367 status = smartcard_pack_list_readers_return(out, &ret, FALSE);
369 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaders);
371 if (status != SCARD_S_SUCCESS)
372 return scard_log_status_error(TAG,
"smartcard_pack_list_readers_return", status);
374 return ret.ReturnCode;
377static LONG smartcard_ListReadersW_Call(scard_call_context* smartcard,
wStream* out,
382 DWORD cchReaders = 0;
398 WINPR_ASSERT(smartcard);
399 WINPR_ASSERT(operation);
401 call = &operation->call.listReaders;
403 string.bp = call->mszGroups;
404 cchReaders = SCARD_AUTOALLOCATE;
405 status = ret.ReturnCode = wrap(smartcard, SCardListReadersW, operation->hContext,
string.wz,
406 (LPWSTR)&mszReaders.pw, &cchReaders);
407 if (status == SCARD_S_SUCCESS)
409 if (cchReaders == SCARD_AUTOALLOCATE)
410 status = SCARD_F_UNKNOWN_ERROR;
413 if (status != SCARD_S_SUCCESS)
415 (void)scard_log_status_error(TAG,
"SCardListReadersW", status);
416 return smartcard_pack_list_readers_return(out, &ret, TRUE);
419 cchReaders = filter_device_by_name_w(smartcard->names, &mszReaders.pw, cchReaders);
420 ret.msz = mszReaders.pb;
421 ret.cBytes = cchReaders *
sizeof(WCHAR);
422 status = smartcard_pack_list_readers_return(out, &ret, TRUE);
425 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaders.pb);
427 if (status != SCARD_S_SUCCESS)
430 return ret.ReturnCode;
433static LONG smartcard_IntroduceReaderGroupA_Call(scard_call_context* smartcard,
434 WINPR_ATTR_UNUSED
wStream* out,
440 WINPR_ASSERT(smartcard);
442 WINPR_ASSERT(operation);
444 call = &operation->call.contextAndStringA;
445 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupA, operation->hContext, call->sz);
446 scard_log_status_error(TAG,
"SCardIntroduceReaderGroupA", ret.ReturnCode);
447 smartcard_trace_long_return(&ret,
"IntroduceReaderGroupA");
448 return ret.ReturnCode;
451static LONG smartcard_IntroduceReaderGroupW_Call(scard_call_context* smartcard,
452 WINPR_ATTR_UNUSED
wStream* out,
458 WINPR_ASSERT(smartcard);
460 WINPR_ASSERT(operation);
462 call = &operation->call.contextAndStringW;
463 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupW, operation->hContext, call->sz);
464 scard_log_status_error(TAG,
"SCardIntroduceReaderGroupW", ret.ReturnCode);
465 smartcard_trace_long_return(&ret,
"IntroduceReaderGroupW");
466 return ret.ReturnCode;
469static LONG smartcard_IntroduceReaderA_Call(scard_call_context* smartcard,
470 WINPR_ATTR_UNUSED
wStream* out,
476 WINPR_ASSERT(smartcard);
478 WINPR_ASSERT(operation);
480 call = &operation->call.contextAndTwoStringA;
482 wrap(smartcard, SCardIntroduceReaderA, operation->hContext, call->sz1, call->sz2);
483 scard_log_status_error(TAG,
"SCardIntroduceReaderA", ret.ReturnCode);
484 smartcard_trace_long_return(&ret,
"IntroduceReaderA");
485 return ret.ReturnCode;
488static LONG smartcard_IntroduceReaderW_Call(scard_call_context* smartcard,
489 WINPR_ATTR_UNUSED
wStream* out,
495 WINPR_ASSERT(smartcard);
497 WINPR_ASSERT(operation);
499 call = &operation->call.contextAndTwoStringW;
501 wrap(smartcard, SCardIntroduceReaderW, operation->hContext, call->sz1, call->sz2);
502 scard_log_status_error(TAG,
"SCardIntroduceReaderW", ret.ReturnCode);
503 smartcard_trace_long_return(&ret,
"IntroduceReaderW");
504 return ret.ReturnCode;
507static LONG smartcard_ForgetReaderA_Call(scard_call_context* smartcard,
508 WINPR_ATTR_UNUSED
wStream* out,
514 WINPR_ASSERT(smartcard);
516 WINPR_ASSERT(operation);
518 call = &operation->call.contextAndStringA;
519 ret.ReturnCode = wrap(smartcard, SCardForgetReaderA, operation->hContext, call->sz);
520 scard_log_status_error(TAG,
"SCardForgetReaderA", ret.ReturnCode);
521 smartcard_trace_long_return(&ret,
"SCardForgetReaderA");
522 return ret.ReturnCode;
525static LONG smartcard_ForgetReaderW_Call(scard_call_context* smartcard,
526 WINPR_ATTR_UNUSED
wStream* out,
532 WINPR_ASSERT(smartcard);
534 WINPR_ASSERT(operation);
536 call = &operation->call.contextAndStringW;
537 ret.ReturnCode = wrap(smartcard, SCardForgetReaderW, operation->hContext, call->sz);
538 scard_log_status_error(TAG,
"SCardForgetReaderW", ret.ReturnCode);
539 smartcard_trace_long_return(&ret,
"SCardForgetReaderW");
540 return ret.ReturnCode;
543static LONG smartcard_AddReaderToGroupA_Call(scard_call_context* smartcard,
544 WINPR_ATTR_UNUSED
wStream* out,
550 WINPR_ASSERT(smartcard);
552 WINPR_ASSERT(operation);
554 call = &operation->call.contextAndTwoStringA;
556 wrap(smartcard, SCardAddReaderToGroupA, operation->hContext, call->sz1, call->sz2);
557 scard_log_status_error(TAG,
"SCardAddReaderToGroupA", ret.ReturnCode);
558 smartcard_trace_long_return(&ret,
"SCardAddReaderToGroupA");
559 return ret.ReturnCode;
562static LONG smartcard_AddReaderToGroupW_Call(scard_call_context* smartcard,
563 WINPR_ATTR_UNUSED
wStream* out,
569 WINPR_ASSERT(smartcard);
571 WINPR_ASSERT(operation);
573 call = &operation->call.contextAndTwoStringW;
575 wrap(smartcard, SCardAddReaderToGroupW, operation->hContext, call->sz1, call->sz2);
576 scard_log_status_error(TAG,
"SCardAddReaderToGroupW", ret.ReturnCode);
577 smartcard_trace_long_return(&ret,
"SCardAddReaderToGroupA");
578 return ret.ReturnCode;
581static LONG smartcard_RemoveReaderFromGroupA_Call(scard_call_context* smartcard,
582 WINPR_ATTR_UNUSED
wStream* out,
588 WINPR_ASSERT(smartcard);
590 WINPR_ASSERT(operation);
592 call = &operation->call.contextAndTwoStringA;
594 wrap(smartcard, SCardRemoveReaderFromGroupA, operation->hContext, call->sz1, call->sz2);
595 scard_log_status_error(TAG,
"SCardRemoveReaderFromGroupA", ret.ReturnCode);
596 smartcard_trace_long_return(&ret,
"SCardRemoveReaderFromGroupA");
597 return ret.ReturnCode;
600static LONG smartcard_RemoveReaderFromGroupW_Call(scard_call_context* smartcard,
601 WINPR_ATTR_UNUSED
wStream* out,
607 WINPR_ASSERT(smartcard);
609 WINPR_ASSERT(operation);
611 call = &operation->call.contextAndTwoStringW;
613 wrap(smartcard, SCardRemoveReaderFromGroupW, operation->hContext, call->sz1, call->sz2);
614 scard_log_status_error(TAG,
"SCardRemoveReaderFromGroupW", ret.ReturnCode);
615 smartcard_trace_long_return(&ret,
"SCardRemoveReaderFromGroupW");
616 return ret.ReturnCode;
619static LONG smartcard_LocateCardsA_Call(scard_call_context* smartcard,
wStream* out,
626 WINPR_ASSERT(smartcard);
627 WINPR_ASSERT(operation);
629 call = &operation->call.locateCardsA;
631 ret.ReturnCode = wrap(smartcard, SCardLocateCardsA, operation->hContext, call->mszCards,
632 call->rgReaderStates, call->cReaders);
633 scard_log_status_error(TAG,
"SCardLocateCardsA", ret.ReturnCode);
634 ret.cReaders = call->cReaders;
635 ret.rgReaderStates = NULL;
637 if (ret.cReaders > 0)
641 if (!ret.rgReaderStates)
642 return STATUS_NO_MEMORY;
645 for (UINT32 x = 0; x < ret.cReaders; x++)
647 ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
648 ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
649 ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
650 CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
651 sizeof(ret.rgReaderStates[x].rgbAtr));
654 status = smartcard_pack_locate_cards_return(out, &ret);
656 if (status != SCARD_S_SUCCESS)
659 return ret.ReturnCode;
662static LONG smartcard_LocateCardsW_Call(scard_call_context* smartcard,
wStream* out,
669 WINPR_ASSERT(smartcard);
670 WINPR_ASSERT(operation);
672 call = &operation->call.locateCardsW;
674 ret.ReturnCode = wrap(smartcard, SCardLocateCardsW, operation->hContext, call->mszCards,
675 call->rgReaderStates, call->cReaders);
676 scard_log_status_error(TAG,
"SCardLocateCardsW", ret.ReturnCode);
677 ret.cReaders = call->cReaders;
678 ret.rgReaderStates = NULL;
680 if (ret.cReaders > 0)
684 if (!ret.rgReaderStates)
685 return STATUS_NO_MEMORY;
688 for (UINT32 x = 0; x < ret.cReaders; x++)
690 ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
691 ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
692 ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
693 CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
694 sizeof(ret.rgReaderStates[x].rgbAtr));
697 status = smartcard_pack_locate_cards_return(out, &ret);
699 if (status != SCARD_S_SUCCESS)
702 return ret.ReturnCode;
705static LONG smartcard_ReadCacheA_Call(scard_call_context* smartcard,
wStream* out,
713 WINPR_ASSERT(smartcard);
715 WINPR_ASSERT(operation);
717 call = &operation->call.readCacheA;
718 autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE);
720 if (!call->Common.fPbDataIsNULL)
722 ret.cbDataLen = call->Common.cbDataLen;
725 ret.pbData = malloc(ret.cbDataLen);
727 return SCARD_F_INTERNAL_ERROR;
732 ret.ReturnCode = wrap(smartcard, SCardReadCacheA, operation->hContext,
733 call->Common.CardIdentifier, call->Common.FreshnessCounter,
734 call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
737 wrap(smartcard, SCardReadCacheA, operation->hContext, call->Common.CardIdentifier,
738 call->Common.FreshnessCounter, call->szLookupName, ret.pbData, &ret.cbDataLen);
739 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
740 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
742 scard_log_status_error(TAG,
"SCardReadCacheA", ret.ReturnCode);
745 status = smartcard_pack_read_cache_return(out, &ret);
747 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
750 if (status != SCARD_S_SUCCESS)
753 return ret.ReturnCode;
756static LONG smartcard_ReadCacheW_Call(scard_call_context* smartcard,
wStream* out,
763 WINPR_ASSERT(smartcard);
765 WINPR_ASSERT(operation);
767 call = &operation->call.readCacheW;
769 if (!call->Common.fPbDataIsNULL)
770 ret.cbDataLen = SCARD_AUTOALLOCATE;
773 wrap(smartcard, SCardReadCacheW, operation->hContext, call->Common.CardIdentifier,
774 call->Common.FreshnessCounter, call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
776 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
777 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
779 scard_log_status_error(TAG,
"SCardReadCacheW", ret.ReturnCode);
782 status = smartcard_pack_read_cache_return(out, &ret);
784 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
786 if (status != SCARD_S_SUCCESS)
789 return ret.ReturnCode;
792static LONG smartcard_WriteCacheA_Call(scard_call_context* smartcard,
793 WINPR_ATTR_UNUSED
wStream* out,
799 WINPR_ASSERT(smartcard);
801 WINPR_ASSERT(operation);
803 call = &operation->call.writeCacheA;
805 ret.ReturnCode = wrap(smartcard, SCardWriteCacheA, operation->hContext,
806 call->Common.CardIdentifier, call->Common.FreshnessCounter,
807 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
808 scard_log_status_error(TAG,
"SCardWriteCacheA", ret.ReturnCode);
809 smartcard_trace_long_return(&ret,
"SCardWriteCacheA");
810 return ret.ReturnCode;
813static LONG smartcard_WriteCacheW_Call(scard_call_context* smartcard,
814 WINPR_ATTR_UNUSED
wStream* out,
820 WINPR_ASSERT(smartcard);
822 WINPR_ASSERT(operation);
824 call = &operation->call.writeCacheW;
826 ret.ReturnCode = wrap(smartcard, SCardWriteCacheW, operation->hContext,
827 call->Common.CardIdentifier, call->Common.FreshnessCounter,
828 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
829 scard_log_status_error(TAG,
"SCardWriteCacheW", ret.ReturnCode);
830 smartcard_trace_long_return(&ret,
"SCardWriteCacheW");
831 return ret.ReturnCode;
834static LONG smartcard_GetTransmitCount_Call(scard_call_context* smartcard,
wStream* out,
840 WINPR_ASSERT(smartcard);
842 WINPR_ASSERT(operation);
844 ret.ReturnCode = wrap(smartcard, SCardGetTransmitCount, operation->hCard, &ret.cTransmitCount);
845 scard_log_status_error(TAG,
"SCardGetTransmitCount", ret.ReturnCode);
846 status = smartcard_pack_get_transmit_count_return(out, &ret);
847 if (status != SCARD_S_SUCCESS)
850 return ret.ReturnCode;
853static LONG smartcard_ReleaseStartedEvent_Call(scard_call_context* smartcard,
wStream* out,
856 WINPR_UNUSED(smartcard);
858 WINPR_UNUSED(operation);
860 WLog_WARN(TAG,
"According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
861 "this is not supported?!?");
862 return SCARD_E_UNSUPPORTED_FEATURE;
865static LONG smartcard_GetReaderIcon_Call(scard_call_context* smartcard,
wStream* out,
872 WINPR_ASSERT(smartcard);
874 WINPR_ASSERT(operation);
876 call = &operation->call.getReaderIcon;
878 ret.cbDataLen = SCARD_AUTOALLOCATE;
879 ret.ReturnCode = wrap(smartcard, SCardGetReaderIconW, operation->hContext, call->szReaderName,
880 (LPBYTE)&ret.pbData, &ret.cbDataLen);
881 scard_log_status_error(TAG,
"SCardGetReaderIconW", ret.ReturnCode);
882 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cbDataLen == SCARD_AUTOALLOCATE))
883 return SCARD_F_UNKNOWN_ERROR;
885 status = smartcard_pack_get_reader_icon_return(out, &ret);
886 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
887 if (status != SCARD_S_SUCCESS)
890 return ret.ReturnCode;
893static LONG smartcard_GetDeviceTypeId_Call(scard_call_context* smartcard,
wStream* out,
900 WINPR_ASSERT(smartcard);
902 WINPR_ASSERT(operation);
904 call = &operation->call.getDeviceTypeId;
906 ret.ReturnCode = wrap(smartcard, SCardGetDeviceTypeIdW, operation->hContext, call->szReaderName,
908 scard_log_status_error(TAG,
"SCardGetDeviceTypeIdW", ret.ReturnCode);
910 status = smartcard_pack_device_type_id_return(out, &ret);
911 if (status != SCARD_S_SUCCESS)
914 return ret.ReturnCode;
917static LONG smartcard_GetStatusChangeA_Call(scard_call_context* smartcard,
wStream* out,
920 LONG status = STATUS_NO_MEMORY;
922 const DWORD dwTimeStep = 100;
927 WINPR_ASSERT(smartcard);
929 WINPR_ASSERT(operation);
931 call = &operation->call.getStatusChangeA;
932 dwTimeOut = call->dwTimeOut;
934 if (call->cReaders > 0)
936 ret.cReaders = call->cReaders;
939 if (!rgReaderStates || !ret.rgReaderStates)
943 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
945 if (call->cReaders > 0)
946 memcpy(rgReaderStates, call->rgReaderStates,
948 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
949 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
950 if (ret.ReturnCode != SCARD_E_TIMEOUT)
952 if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
954 if (dwTimeOut != INFINITE)
957 scard_log_status_error(TAG,
"SCardGetStatusChangeA", ret.ReturnCode);
959 for (UINT32 index = 0; index < ret.cReaders; index++)
964 rout->dwCurrentState = cur->dwCurrentState;
965 rout->dwEventState = cur->dwEventState;
966 rout->cbAtr = cur->cbAtr;
967 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
970 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
972 free(ret.rgReaderStates);
973 free(rgReaderStates);
974 if (status != SCARD_S_SUCCESS)
976 return ret.ReturnCode;
979static LONG smartcard_GetStatusChangeW_Call(scard_call_context* smartcard,
wStream* out,
982 LONG status = STATUS_NO_MEMORY;
984 const DWORD dwTimeStep = 100;
988 WINPR_ASSERT(smartcard);
990 WINPR_ASSERT(operation);
993 dwTimeOut = call->dwTimeOut;
995 if (call->cReaders > 0)
997 ret.cReaders = call->cReaders;
1000 if (!rgReaderStates || !ret.rgReaderStates)
1004 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
1006 if (call->cReaders > 0)
1007 memcpy(rgReaderStates, call->rgReaderStates,
1010 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
1011 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
1013 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1015 if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
1017 if (dwTimeOut != INFINITE)
1020 scard_log_status_error(TAG,
"SCardGetStatusChangeW", ret.ReturnCode);
1022 for (UINT32 index = 0; index < ret.cReaders; index++)
1027 rout->dwCurrentState = cur->dwCurrentState;
1028 rout->dwEventState = cur->dwEventState;
1029 rout->cbAtr = cur->cbAtr;
1030 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1033 status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
1035 free(ret.rgReaderStates);
1036 free(rgReaderStates);
1037 if (status != SCARD_S_SUCCESS)
1039 return ret.ReturnCode;
1042static LONG smartcard_Cancel_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1047 WINPR_ASSERT(smartcard);
1049 WINPR_ASSERT(operation);
1051 ret.ReturnCode = wrap(smartcard, SCardCancel, operation->hContext);
1052 scard_log_status_error(TAG,
"SCardCancel", ret.ReturnCode);
1053 smartcard_trace_long_return(&ret,
"Cancel");
1054 return ret.ReturnCode;
1057static LONG smartcard_ConnectA_Call(scard_call_context* smartcard,
wStream* out,
1061 SCARDHANDLE hCard = 0;
1065 WINPR_ASSERT(smartcard);
1067 WINPR_ASSERT(operation);
1069 call = &operation->call.connectA;
1071 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1072 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1074 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1077 ret.ReturnCode = wrap(smartcard, SCardConnectA, operation->hContext, (
char*)call->szReader,
1078 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1079 &ret.dwActiveProtocol);
1080 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1081 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1083 status = smartcard_pack_connect_return(out, &ret);
1084 if (status != SCARD_S_SUCCESS)
1087 status = ret.ReturnCode;
1093static LONG smartcard_ConnectW_Call(scard_call_context* smartcard,
wStream* out,
1097 SCARDHANDLE hCard = 0;
1101 WINPR_ASSERT(smartcard);
1103 WINPR_ASSERT(operation);
1105 call = &operation->call.connectW;
1107 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1108 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1110 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1113 ret.ReturnCode = wrap(smartcard, SCardConnectW, operation->hContext, (WCHAR*)call->szReader,
1114 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1115 &ret.dwActiveProtocol);
1116 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1117 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1119 status = smartcard_pack_connect_return(out, &ret);
1120 if (status != SCARD_S_SUCCESS)
1123 status = ret.ReturnCode;
1129static LONG smartcard_Reconnect_Call(scard_call_context* smartcard,
wStream* out,
1136 WINPR_ASSERT(smartcard);
1138 WINPR_ASSERT(operation);
1140 call = &operation->call.reconnect;
1142 wrap(smartcard, SCardReconnect, operation->hCard, call->dwShareMode,
1143 call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
1144 scard_log_status_error(TAG,
"SCardReconnect", ret.ReturnCode);
1145 status = smartcard_pack_reconnect_return(out, &ret);
1146 if (status != SCARD_S_SUCCESS)
1149 return ret.ReturnCode;
1152static LONG smartcard_Disconnect_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1158 WINPR_ASSERT(smartcard);
1160 WINPR_ASSERT(operation);
1162 call = &operation->call.hCardAndDisposition;
1164 ret.ReturnCode = wrap(smartcard, SCardDisconnect, operation->hCard, call->dwDisposition);
1165 scard_log_status_error(TAG,
"SCardDisconnect", ret.ReturnCode);
1166 smartcard_trace_long_return(&ret,
"Disconnect");
1168 return ret.ReturnCode;
1171static LONG smartcard_BeginTransaction_Call(scard_call_context* smartcard,
1172 WINPR_ATTR_UNUSED
wStream* out,
1177 WINPR_ASSERT(smartcard);
1179 WINPR_ASSERT(operation);
1181 ret.ReturnCode = wrap(smartcard, SCardBeginTransaction, operation->hCard);
1182 scard_log_status_error(TAG,
"SCardBeginTransaction", ret.ReturnCode);
1183 smartcard_trace_long_return(&ret,
"BeginTransaction");
1184 return ret.ReturnCode;
1187static LONG smartcard_EndTransaction_Call(scard_call_context* smartcard,
1188 WINPR_ATTR_UNUSED
wStream* out,
1194 WINPR_ASSERT(smartcard);
1196 WINPR_ASSERT(operation);
1198 call = &operation->call.hCardAndDisposition;
1200 ret.ReturnCode = wrap(smartcard, SCardEndTransaction, operation->hCard, call->dwDisposition);
1201 scard_log_status_error(TAG,
"SCardEndTransaction", ret.ReturnCode);
1202 smartcard_trace_long_return(&ret,
"EndTransaction");
1203 return ret.ReturnCode;
1206static LONG smartcard_State_Call(scard_call_context* smartcard,
wStream* out,
1212 WINPR_ASSERT(smartcard);
1214 WINPR_ASSERT(operation);
1216 ret.cbAtrLen = SCARD_ATR_LENGTH;
1217 ret.ReturnCode = wrap(smartcard, SCardState, operation->hCard, &ret.dwState, &ret.dwProtocol,
1218 (BYTE*)&ret.rgAtr, &ret.cbAtrLen);
1220 scard_log_status_error(TAG,
"SCardState", ret.ReturnCode);
1221 status = smartcard_pack_state_return(out, &ret);
1222 if (status != SCARD_S_SUCCESS)
1225 return ret.ReturnCode;
1228static LONG smartcard_StatusA_Call(scard_call_context* smartcard,
wStream* out,
1233 DWORD cchReaderLen = 0;
1235 LPSTR mszReaderNames = NULL;
1238 WINPR_ASSERT(smartcard);
1240 WINPR_ASSERT(operation);
1242 call = &operation->call.status;
1244 call->cbAtrLen = 32;
1245 cbAtrLen = call->cbAtrLen;
1247 if (call->fmszReaderNamesIsNULL)
1250 cchReaderLen = SCARD_AUTOALLOCATE;
1252 status = ret.ReturnCode =
1253 wrap(smartcard, SCardStatusA, operation->hCard,
1254 call->fmszReaderNamesIsNULL ? NULL : (LPSTR)&mszReaderNames, &cchReaderLen,
1255 &ret.dwState, &ret.dwProtocol, cbAtrLen ? (BYTE*)&ret.pbAtr : NULL, &cbAtrLen);
1257 scard_log_status_error(TAG,
"SCardStatusA", status);
1258 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchReaderLen == SCARD_AUTOALLOCATE))
1259 return SCARD_F_UNKNOWN_ERROR;
1261 if (status == SCARD_S_SUCCESS)
1263 if (!call->fmszReaderNamesIsNULL)
1264 ret.mszReaderNames = (BYTE*)mszReaderNames;
1266 ret.cBytes = cchReaderLen;
1269 ret.cbAtrLen = cbAtrLen;
1272 status = smartcard_pack_status_return(out, &ret, FALSE);
1275 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1277 if (status != SCARD_S_SUCCESS)
1279 return ret.ReturnCode;
1282static LONG smartcard_StatusW_Call(scard_call_context* smartcard,
wStream* out,
1287 LPWSTR mszReaderNames = NULL;
1291 WINPR_ASSERT(smartcard);
1293 WINPR_ASSERT(operation);
1295 call = &operation->call.status;
1301 cbAtrLen = call->cbAtrLen = 32;
1303 if (call->fmszReaderNamesIsNULL)
1306 ret.cBytes = SCARD_AUTOALLOCATE;
1308 status = ret.ReturnCode =
1309 wrap(smartcard, SCardStatusW, operation->hCard,
1310 call->fmszReaderNamesIsNULL ? NULL : (LPWSTR)&mszReaderNames, &ret.cBytes,
1311 &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
1312 scard_log_status_error(TAG,
"SCardStatusW", status);
1313 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cBytes == SCARD_AUTOALLOCATE))
1314 return SCARD_F_UNKNOWN_ERROR;
1316 if (status == SCARD_S_SUCCESS)
1318 if (!call->fmszReaderNamesIsNULL)
1319 ret.mszReaderNames = (BYTE*)mszReaderNames;
1321 ret.cbAtrLen = cbAtrLen;
1325 WINPR_ASSERT(ret.cBytes < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
1326 const size_t blen =
sizeof(WCHAR) * ret.cBytes;
1327 WINPR_ASSERT(blen <= UINT32_MAX);
1328 ret.cBytes = (UINT32)blen;
1330 status = smartcard_pack_status_return(out, &ret, TRUE);
1331 if (status != SCARD_S_SUCCESS)
1335 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1337 return ret.ReturnCode;
1340static LONG smartcard_Transmit_Call(scard_call_context* smartcard,
wStream* out,
1347 WINPR_ASSERT(smartcard);
1349 WINPR_ASSERT(operation);
1351 call = &operation->call.transmit;
1352 ret.cbRecvLength = 0;
1353 ret.pbRecvBuffer = NULL;
1355 if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
1357 if (call->cbRecvLength >= 66560)
1358 call->cbRecvLength = 66560;
1360 ret.cbRecvLength = call->cbRecvLength;
1361 ret.pbRecvBuffer = (BYTE*)malloc(ret.cbRecvLength);
1363 if (!ret.pbRecvBuffer)
1364 return STATUS_NO_MEMORY;
1367 ret.pioRecvPci = call->pioRecvPci;
1369 wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
1370 call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
1372 scard_log_status_error(TAG,
"SCardTransmit", ret.ReturnCode);
1374 status = smartcard_pack_transmit_return(out, &ret);
1375 free(ret.pbRecvBuffer);
1377 if (status != SCARD_S_SUCCESS)
1379 return ret.ReturnCode;
1382static LONG smartcard_Control_Call(scard_call_context* smartcard,
wStream* out,
1389 WINPR_ASSERT(smartcard);
1391 WINPR_ASSERT(operation);
1393 call = &operation->call.control;
1394 ret.cbOutBufferSize = call->cbOutBufferSize;
1395 ret.pvOutBuffer = (BYTE*)malloc(call->cbOutBufferSize);
1397 if (!ret.pvOutBuffer)
1398 return SCARD_E_NO_MEMORY;
1401 wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
1402 call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
1403 scard_log_status_error(TAG,
"SCardControl", ret.ReturnCode);
1404 status = smartcard_pack_control_return(out, &ret);
1406 free(ret.pvOutBuffer);
1407 if (status != SCARD_S_SUCCESS)
1409 return ret.ReturnCode;
1412static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard,
wStream* out,
1415 BOOL autoAllocate = FALSE;
1417 DWORD cbAttrLen = 0;
1418 LPBYTE pbAttr = NULL;
1422 WINPR_ASSERT(smartcard);
1423 WINPR_ASSERT(operation);
1425 call = &operation->call.getAttrib;
1427 if (!call->fpbAttrIsNULL)
1429 autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE) ? TRUE : FALSE;
1430 cbAttrLen = call->cbAttrLen;
1431 if (cbAttrLen && !autoAllocate)
1433 ret.pbAttr = (BYTE*)malloc(cbAttrLen);
1436 return SCARD_E_NO_MEMORY;
1439 pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
1443 wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
1444 scard_log_status_error(TAG,
"SCardGetAttrib", ret.ReturnCode);
1445 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cbAttrLen == SCARD_AUTOALLOCATE))
1446 return SCARD_F_UNKNOWN_ERROR;
1448 ret.cbAttrLen = cbAttrLen;
1450 status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
1453 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
1459static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1465 WINPR_ASSERT(smartcard);
1467 WINPR_ASSERT(operation);
1469 call = &operation->call.setAttrib;
1471 ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
1473 scard_log_status_error(TAG,
"SCardSetAttrib", ret.ReturnCode);
1474 smartcard_trace_long_return(&ret,
"SetAttrib");
1476 return ret.ReturnCode;
1479static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard,
1480 WINPR_ATTR_UNUSED
wStream* out,
1483 LONG status = SCARD_S_SUCCESS;
1485 WINPR_ASSERT(smartcard);
1487 WINPR_UNUSED(operation);
1489 if (!smartcard->StartedEvent)
1490 smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
1492 if (!smartcard->StartedEvent)
1493 status = SCARD_E_NO_SERVICE;
1498static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard,
wStream* out,
1506 WINPR_ASSERT(smartcard);
1507 WINPR_ASSERT(operation);
1509 call = &operation->call.locateCardsByATRA;
1513 return STATUS_NO_MEMORY;
1515 for (UINT32 i = 0; i < call->cReaders; i++)
1518 state->szReader = call->rgReaderStates[i].szReader;
1519 state->dwCurrentState = call->rgReaderStates[i].dwCurrentState;
1520 state->dwEventState = call->rgReaderStates[i].dwEventState;
1521 state->cbAtr = call->rgReaderStates[i].cbAtr;
1522 CopyMemory(&(state->rgbAtr), &(call->rgReaderStates[i].rgbAtr), 36);
1525 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1526 0x000001F4, states, call->cReaders);
1528 scard_log_status_error(TAG,
"SCardGetStatusChangeA", status);
1529 for (UINT32 i = 0; i < call->cAtrs; i++)
1531 for (UINT32 j = 0; j < call->cReaders; j++)
1533 for (UINT32 k = 0; k < call->rgAtrMasks[i].cbAtr; k++)
1535 if ((call->rgAtrMasks[i].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]) !=
1536 (states[j].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]))
1541 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1546 ret.cReaders = call->cReaders;
1547 ret.rgReaderStates = NULL;
1549 if (ret.cReaders > 0)
1552 if (!ret.rgReaderStates)
1555 return STATUS_NO_MEMORY;
1558 for (UINT32 i = 0; i < ret.cReaders; i++)
1561 ret.rgReaderStates[i].dwCurrentState = state->dwCurrentState;
1562 ret.rgReaderStates[i].dwEventState = state->dwEventState;
1563 ret.rgReaderStates[i].cbAtr = state->cbAtr;
1564 CopyMemory(&(ret.rgReaderStates[i].rgbAtr), &(state->rgbAtr),
1565 sizeof(ret.rgReaderStates[i].rgbAtr));
1570 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1572 free(ret.rgReaderStates);
1573 if (status != SCARD_S_SUCCESS)
1575 return ret.ReturnCode;
1578LONG smartcard_irp_device_control_call(scard_call_context* smartcard,
wStream* out,
1583 size_t outputBufferLength = 0;
1584 size_t objectBufferLength = 0;
1586 WINPR_ASSERT(smartcard);
1588 WINPR_ASSERT(pIoStatus);
1589 WINPR_ASSERT(operation);
1591 const UINT32 ioControlCode = operation->ioControlCode;
1599 const size_t outMaxLen = MAX(2048, operation->outputBufferLength);
1600 if (!Stream_EnsureRemainingCapacity(out, outMaxLen))
1601 return SCARD_E_NO_MEMORY;
1604 Stream_Write_UINT32(out, 0);
1605 Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH);
1606 Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH);
1607 Stream_Write_UINT32(out, 0);
1610 switch (ioControlCode)
1612 case SCARD_IOCTL_ESTABLISHCONTEXT:
1613 result = smartcard_EstablishContext_Call(smartcard, out, operation);
1616 case SCARD_IOCTL_RELEASECONTEXT:
1617 result = smartcard_ReleaseContext_Call(smartcard, out, operation);
1620 case SCARD_IOCTL_ISVALIDCONTEXT:
1621 result = smartcard_IsValidContext_Call(smartcard, out, operation);
1624 case SCARD_IOCTL_LISTREADERGROUPSA:
1625 result = smartcard_ListReaderGroupsA_Call(smartcard, out, operation);
1628 case SCARD_IOCTL_LISTREADERGROUPSW:
1629 result = smartcard_ListReaderGroupsW_Call(smartcard, out, operation);
1632 case SCARD_IOCTL_LISTREADERSA:
1633 result = smartcard_ListReadersA_Call(smartcard, out, operation);
1636 case SCARD_IOCTL_LISTREADERSW:
1637 result = smartcard_ListReadersW_Call(smartcard, out, operation);
1640 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1641 result = smartcard_IntroduceReaderGroupA_Call(smartcard, out, operation);
1644 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1645 result = smartcard_IntroduceReaderGroupW_Call(smartcard, out, operation);
1648 case SCARD_IOCTL_FORGETREADERGROUPA:
1649 result = smartcard_ForgetReaderA_Call(smartcard, out, operation);
1652 case SCARD_IOCTL_FORGETREADERGROUPW:
1653 result = smartcard_ForgetReaderW_Call(smartcard, out, operation);
1656 case SCARD_IOCTL_INTRODUCEREADERA:
1657 result = smartcard_IntroduceReaderA_Call(smartcard, out, operation);
1660 case SCARD_IOCTL_INTRODUCEREADERW:
1661 result = smartcard_IntroduceReaderW_Call(smartcard, out, operation);
1664 case SCARD_IOCTL_FORGETREADERA:
1665 result = smartcard_ForgetReaderA_Call(smartcard, out, operation);
1668 case SCARD_IOCTL_FORGETREADERW:
1669 result = smartcard_ForgetReaderW_Call(smartcard, out, operation);
1672 case SCARD_IOCTL_ADDREADERTOGROUPA:
1673 result = smartcard_AddReaderToGroupA_Call(smartcard, out, operation);
1676 case SCARD_IOCTL_ADDREADERTOGROUPW:
1677 result = smartcard_AddReaderToGroupW_Call(smartcard, out, operation);
1680 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1681 result = smartcard_RemoveReaderFromGroupA_Call(smartcard, out, operation);
1684 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1685 result = smartcard_RemoveReaderFromGroupW_Call(smartcard, out, operation);
1688 case SCARD_IOCTL_LOCATECARDSA:
1689 result = smartcard_LocateCardsA_Call(smartcard, out, operation);
1692 case SCARD_IOCTL_LOCATECARDSW:
1693 result = smartcard_LocateCardsW_Call(smartcard, out, operation);
1696 case SCARD_IOCTL_GETSTATUSCHANGEA:
1697 result = smartcard_GetStatusChangeA_Call(smartcard, out, operation);
1700 case SCARD_IOCTL_GETSTATUSCHANGEW:
1701 result = smartcard_GetStatusChangeW_Call(smartcard, out, operation);
1704 case SCARD_IOCTL_CANCEL:
1705 result = smartcard_Cancel_Call(smartcard, out, operation);
1708 case SCARD_IOCTL_CONNECTA:
1709 result = smartcard_ConnectA_Call(smartcard, out, operation);
1712 case SCARD_IOCTL_CONNECTW:
1713 result = smartcard_ConnectW_Call(smartcard, out, operation);
1716 case SCARD_IOCTL_RECONNECT:
1717 result = smartcard_Reconnect_Call(smartcard, out, operation);
1720 case SCARD_IOCTL_DISCONNECT:
1721 result = smartcard_Disconnect_Call(smartcard, out, operation);
1724 case SCARD_IOCTL_BEGINTRANSACTION:
1725 result = smartcard_BeginTransaction_Call(smartcard, out, operation);
1728 case SCARD_IOCTL_ENDTRANSACTION:
1729 result = smartcard_EndTransaction_Call(smartcard, out, operation);
1732 case SCARD_IOCTL_STATE:
1733 result = smartcard_State_Call(smartcard, out, operation);
1736 case SCARD_IOCTL_STATUSA:
1737 result = smartcard_StatusA_Call(smartcard, out, operation);
1740 case SCARD_IOCTL_STATUSW:
1741 result = smartcard_StatusW_Call(smartcard, out, operation);
1744 case SCARD_IOCTL_TRANSMIT:
1745 result = smartcard_Transmit_Call(smartcard, out, operation);
1748 case SCARD_IOCTL_CONTROL:
1749 result = smartcard_Control_Call(smartcard, out, operation);
1752 case SCARD_IOCTL_GETATTRIB:
1753 result = smartcard_GetAttrib_Call(smartcard, out, operation);
1756 case SCARD_IOCTL_SETATTRIB:
1757 result = smartcard_SetAttrib_Call(smartcard, out, operation);
1760 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
1761 result = smartcard_AccessStartedEvent_Call(smartcard, out, operation);
1764 case SCARD_IOCTL_LOCATECARDSBYATRA:
1765 result = smartcard_LocateCardsByATRA_Call(smartcard, out, operation);
1768 case SCARD_IOCTL_LOCATECARDSBYATRW:
1769 result = smartcard_LocateCardsW_Call(smartcard, out, operation);
1772 case SCARD_IOCTL_READCACHEA:
1773 result = smartcard_ReadCacheA_Call(smartcard, out, operation);
1776 case SCARD_IOCTL_READCACHEW:
1777 result = smartcard_ReadCacheW_Call(smartcard, out, operation);
1780 case SCARD_IOCTL_WRITECACHEA:
1781 result = smartcard_WriteCacheA_Call(smartcard, out, operation);
1784 case SCARD_IOCTL_WRITECACHEW:
1785 result = smartcard_WriteCacheW_Call(smartcard, out, operation);
1788 case SCARD_IOCTL_GETTRANSMITCOUNT:
1789 result = smartcard_GetTransmitCount_Call(smartcard, out, operation);
1792 case SCARD_IOCTL_RELEASETARTEDEVENT:
1793 result = smartcard_ReleaseStartedEvent_Call(smartcard, out, operation);
1796 case SCARD_IOCTL_GETREADERICON:
1797 result = smartcard_GetReaderIcon_Call(smartcard, out, operation);
1800 case SCARD_IOCTL_GETDEVICETYPEID:
1801 result = smartcard_GetDeviceTypeId_Call(smartcard, out, operation);
1805 result = STATUS_UNSUCCESSFUL;
1815 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
1816 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
1818 offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
1819 smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
1822 if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
1823 (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
1824 (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
1826 WLog_WARN(TAG,
"IRP failure: %s (0x%08" PRIX32
"), status: %s (0x%08" PRIX32
")",
1827 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
1828 SCardGetErrorString(result), result);
1831 *pIoStatus = STATUS_SUCCESS;
1833 if ((result & 0xC0000000L) == 0xC0000000L)
1836 *pIoStatus = result;
1837 WLog_WARN(TAG,
"IRP failure: %s (0x%08" PRIX32
"), ntstatus: 0x%08" PRIX32
"",
1838 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, result);
1841 Stream_SealLength(out);
1842 outputBufferLength = Stream_Length(out);
1843 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH - 4U);
1844 outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1845 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1846 objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
1847 WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
1848 WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
1849 Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1851 if (outputBufferLength > operation->outputBufferLength)
1853 WLog_WARN(TAG,
"IRP warn: expected outputBufferLength %" PRIu32
", but have %" PRIu32,
1854 operation->outputBufferLength, outputBufferLength);
1858 Stream_Write_UINT32(out, (UINT32)outputBufferLength);
1859 smartcard_pack_common_type_header(out);
1860 smartcard_pack_private_type_header(
1861 out, (UINT32)objectBufferLength);
1862 Stream_Write_INT32(out, result);
1863 Stream_SetPosition(out, Stream_Length(out));
1864 return SCARD_S_SUCCESS;
1867void context_free(
void* arg)
1869 struct s_scard_context_element* element = arg;
1873 if (element->fn_free)
1874 element->fn_free(element->context);
1878scard_call_context* smartcard_call_context_new(
const rdpSettings* settings)
1881 scard_call_context* ctx = NULL;
1883 WINPR_ASSERT(settings);
1884 ctx = calloc(1,
sizeof(scard_call_context));
1888 ctx->stopEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
1889 if (!ctx->stopEvent)
1892 ctx->names = LinkedList_New();
1896#if defined(WITH_SMARTCARD_EMULATE)
1900 if (ctx->useEmulatedCard)
1902#if defined(WITH_SMARTCARD_EMULATE)
1903 ctx->emulation = Emulate_New(settings);
1904 if (!ctx->emulation)
1907 WLog_ERR(TAG,
"Smartcard emulation requested, but not supported!");
1916 ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
1918 if (!ctx->hWinSCardLibrary)
1920 WLog_ERR(TAG,
"Failed to load WinSCard library: '%s'", WinSCardModule);
1924 if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
1926 ctx->pWinSCardApi = &ctx->WinSCardApi;
1930 ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
1933 if (!ctx->pWinSCardApi)
1935 WLog_ERR(TAG,
"Failed to load WinSCard API!");
1940 ctx->rgSCardContextList = HashTable_New(FALSE);
1941 if (!ctx->rgSCardContextList)
1944 obj = HashTable_ValueObject(ctx->rgSCardContextList);
1946 obj->fnObjectFree = context_free;
1950 WINPR_PRAGMA_DIAG_PUSH
1951 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1952 smartcard_call_context_free(ctx);
1953 WINPR_PRAGMA_DIAG_POP
1957void smartcard_call_context_free(scard_call_context* ctx)
1962 smartcard_call_context_signal_stop(ctx, FALSE);
1964 LinkedList_Free(ctx->names);
1965 if (ctx->StartedEvent)
1967 WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
1968 wrap(ctx, SCardReleaseStartedEvent);
1971 if (ctx->useEmulatedCard)
1973#ifdef WITH_SMARTCARD_EMULATE
1976 Emulate_Free(ctx->emulation);
1977 ctx->emulation = NULL;
1982 if (ctx->hWinSCardLibrary)
1985 FreeLibrary(ctx->hWinSCardLibrary);
1986 ctx->hWinSCardLibrary = NULL;
1989 ctx->pWinSCardApi = NULL;
1991 HashTable_Free(ctx->rgSCardContextList);
1992 (void)CloseHandle(ctx->stopEvent);
1996BOOL smartcard_call_context_add(scard_call_context* ctx,
const char* name)
2000 return LinkedList_AddLast(ctx->names, name);
2003BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2006 if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
2008 wrap(ctx, SCardCancel, hContext);
2013BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2016 wrap(ctx, SCardReleaseContext, hContext);
2020BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
2024 HashTable_Clear(ctx->rgSCardContextList);
2028BOOL smarcard_call_set_callbacks(scard_call_context* ctx,
void* userdata,
2029 void* (*fn_new)(
void*, SCARDCONTEXT),
void (*fn_free)(
void*))
2032 ctx->userdata = userdata;
2033 ctx->fn_new = fn_new;
2034 ctx->fn_free = fn_free;
2038void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2040 struct s_scard_context_element* element = NULL;
2043 element = HashTable_GetItemValue(ctx->rgSCardContextList, (
void*)hContext);
2046 return element->context;
2049BOOL smartcard_call_is_configured(scard_call_context* ctx)
2053#if defined(WITH_SMARTCARD_EMULATE)
2054 if (ctx->useEmulatedCard)
2055 return Emulate_IsConfigured(ctx->emulation);
2061BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
2064 if (!ctx->stopEvent)
2068 return ResetEvent(ctx->stopEvent);
2070 return SetEvent(ctx->stopEvent);
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
This struct contains function pointer to initialize/free objects.