26#include <freerdp/config.h>
28#include <winpr/assert.h>
31#include <winpr/print.h>
32#include <winpr/stream.h>
33#include <winpr/library.h>
34#include <winpr/smartcard.h>
36#include <freerdp/freerdp.h>
37#include <freerdp/channels/rdpdr.h>
38#include <freerdp/channels/scard.h>
40#include <freerdp/utils/rdpdr_utils.h>
41#include <freerdp/utils/smartcard_pack.h>
42#include <freerdp/utils/smartcard_call.h>
44#include "smartcard_pack.h"
46#include <freerdp/log.h>
47#define SCARD_TAG FREERDP_TAG("utils.smartcard.call")
49#if defined(WITH_SMARTCARD_EMULATE)
50#include <freerdp/emulate/scard/smartcard_emulate.h>
52#define wrap(ctx, fkt, ...) \
53 ctx->useEmulatedCard ? Emulate_##fkt(ctx->emulation, ##__VA_ARGS__) \
54 : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
55#define wrap_ptr(ctx, fkt, ...) wrap(ctx, fkt, ##__VA_ARGS__)
57#define wrap(ctx, fkt, ...) \
58 ctx->useEmulatedCard ? SCARD_F_INTERNAL_ERROR : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
59#define wrap_ptr(ctx, fkt, ...) \
60 ctx->useEmulatedCard ? NULL : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
63struct s_scard_call_context
68 wHashTable* rgSCardContextList;
69#if defined(WITH_SMARTCARD_EMULATE)
70 SmartcardEmulationContext* emulation;
72 HANDLE hWinSCardLibrary;
78 void* (*fn_new)(
void*, SCARDCONTEXT);
79 void (*fn_free)(
void*);
83struct s_scard_context_element
86 void (*fn_free)(
void*);
89static void context_free(
void* arg);
91static LONG smartcard_EstablishContext_Call(scard_call_context* smartcard,
wStream* out,
95 SCARDCONTEXT hContext = { 0 };
98 status = ret.ReturnCode =
99 wrap(smartcard, SCardEstablishContext, call->dwScope, NULL, NULL, &hContext);
101 if (ret.ReturnCode == SCARD_S_SUCCESS)
103 const void* key = (
void*)(
size_t)hContext;
104 struct s_scard_context_element* pContext =
105 calloc(1,
sizeof(
struct s_scard_context_element));
107 return STATUS_NO_MEMORY;
109 pContext->fn_free = smartcard->fn_free;
111 if (smartcard->fn_new)
113 pContext->context = smartcard->fn_new(smartcard->userdata, hContext);
114 if (!pContext->context)
117 return STATUS_NO_MEMORY;
121 if (!HashTable_Insert(smartcard->rgSCardContextList, key, (
void*)pContext))
123 WLog_Print(smartcard->log, WLOG_ERROR,
"ListDictionary_Add failed!");
124 context_free(pContext);
125 return STATUS_INTERNAL_ERROR;
130 return scard_log_status_error_wlog(smartcard->log,
"SCardEstablishContext", status);
134 smartcard_scard_context_native_to_redir(&(ret.hContext), hContext);
136 status = smartcard_pack_establish_context_return(out, &ret);
137 if (status != SCARD_S_SUCCESS)
139 return scard_log_status_error_wlog(smartcard->log,
140 "smartcard_pack_establish_context_return", status);
143 return ret.ReturnCode;
146static LONG smartcard_ReleaseContext_Call(scard_call_context* smartcard,
147 WINPR_ATTR_UNUSED
wStream* out,
152 WINPR_ASSERT(smartcard);
154 WINPR_ASSERT(operation);
156 ret.ReturnCode = wrap(smartcard, SCardReleaseContext, operation->hContext);
158 if (ret.ReturnCode == SCARD_S_SUCCESS)
159 HashTable_Remove(smartcard->rgSCardContextList, (
void*)operation->hContext);
162 return scard_log_status_error_wlog(smartcard->log,
"SCardReleaseContext", ret.ReturnCode);
165 smartcard_trace_long_return_int(smartcard->log, &ret,
"ReleaseContext");
166 return ret.ReturnCode;
169static LONG smartcard_IsValidContext_Call(scard_call_context* smartcard,
170 WINPR_ATTR_UNUSED
wStream* out,
175 WINPR_ASSERT(smartcard);
177 WINPR_ASSERT(operation);
179 ret.ReturnCode = wrap(smartcard, SCardIsValidContext, operation->hContext);
180 smartcard_trace_long_return_int(smartcard->log, &ret,
"IsValidContext");
181 return ret.ReturnCode;
184static LONG smartcard_ListReaderGroupsA_Call(scard_call_context* smartcard,
wStream* out,
189 LPSTR mszGroups = NULL;
192 WINPR_ASSERT(smartcard);
194 WINPR_ASSERT(operation);
196 cchGroups = SCARD_AUTOALLOCATE;
198 wrap(smartcard, SCardListReaderGroupsA, operation->hContext, (LPSTR)&mszGroups, &cchGroups);
199 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchGroups == SCARD_AUTOALLOCATE))
200 return SCARD_F_UNKNOWN_ERROR;
202 ret.msz = (BYTE*)mszGroups;
203 ret.cBytes = cchGroups;
205 status = smartcard_pack_list_reader_groups_return(out, &ret, FALSE);
207 if (status != SCARD_S_SUCCESS)
211 wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
213 return ret.ReturnCode;
216static LONG smartcard_ListReaderGroupsW_Call(scard_call_context* smartcard,
wStream* out,
221 LPWSTR mszGroups = NULL;
224 WINPR_ASSERT(smartcard);
226 WINPR_ASSERT(operation);
228 cchGroups = SCARD_AUTOALLOCATE;
229 status = ret.ReturnCode = wrap(smartcard, SCardListReaderGroupsW, operation->hContext,
230 (LPWSTR)&mszGroups, &cchGroups);
231 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchGroups == SCARD_AUTOALLOCATE))
232 return SCARD_F_UNKNOWN_ERROR;
234 ret.msz = (BYTE*)mszGroups;
236 WINPR_ASSERT(cchGroups < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
237 const size_t blen =
sizeof(WCHAR) * cchGroups;
238 WINPR_ASSERT(blen <= UINT32_MAX);
239 ret.cBytes = (UINT32)blen;
241 if (status != SCARD_S_SUCCESS)
244 status = smartcard_pack_list_reader_groups_return(out, &ret, TRUE);
246 if (status != SCARD_S_SUCCESS)
250 wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
252 return ret.ReturnCode;
255static BOOL filter_match(wLinkedList* list, LPCSTR reader,
size_t readerLen)
260 LinkedList_Enumerator_Reset(list);
262 while (LinkedList_Enumerator_MoveNext(list))
264 const char* filter = LinkedList_Enumerator_Current(list);
268 if (strstr(reader, filter) != NULL)
276static DWORD filter_device_by_name_a(wLinkedList* list, LPSTR* mszReaders, DWORD cchReaders)
281 if (*mszReaders == NULL || LinkedList_Count(list) < 1)
286 LPCSTR rreader = &(*mszReaders)[rpos];
287 LPSTR wreader = &(*mszReaders)[wpos];
288 size_t readerLen = strnlen(rreader, cchReaders - rpos);
290 rpos += readerLen + 1;
292 if (filter_match(list, rreader, readerLen))
294 if (rreader != wreader)
295 memmove(wreader, rreader, readerLen + 1);
297 wpos += readerLen + 1;
299 }
while (rpos < cchReaders);
304 if (wpos >= cchReaders)
307 (*mszReaders)[wpos++] =
'\0';
313static DWORD filter_device_by_name_w(wLinkedList* list, LPWSTR* mszReaders, DWORD cchReaders)
316 LPSTR readers = NULL;
318 if (LinkedList_Count(list) < 1)
321 readers = ConvertMszWCharNToUtf8Alloc(*mszReaders, cchReaders, NULL);
331 rc = filter_device_by_name_a(list, &readers, cchReaders);
333 *mszReaders = ConvertMszUtf8NToWCharAlloc(readers, rc, NULL);
341static LONG smartcard_ListReadersA_Call(scard_call_context* smartcard,
wStream* out,
345 LPSTR mszReaders = NULL;
347 WINPR_ASSERT(smartcard);
349 WINPR_ASSERT(operation);
352 DWORD cchReaders = SCARD_AUTOALLOCATE;
353 LONG status = ret.ReturnCode = wrap(smartcard, SCardListReadersA, operation->hContext,
354 (LPCSTR)call->mszGroups, (LPSTR)&mszReaders, &cchReaders);
355 if (status == SCARD_S_SUCCESS)
357 if (cchReaders == SCARD_AUTOALLOCATE)
358 status = SCARD_F_UNKNOWN_ERROR;
361 if (status != SCARD_S_SUCCESS)
363 (void)scard_log_status_error_wlog(smartcard->log,
"SCardListReadersA", status);
364 return smartcard_pack_list_readers_return(out, &ret, FALSE);
367 cchReaders = filter_device_by_name_a(smartcard->names, &mszReaders, cchReaders);
368 ret.msz = (BYTE*)mszReaders;
369 ret.cBytes = cchReaders;
371 status = smartcard_pack_list_readers_return(out, &ret, FALSE);
373 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaders);
375 if (status != SCARD_S_SUCCESS)
376 return scard_log_status_error_wlog(smartcard->log,
"smartcard_pack_list_readers_return",
379 return ret.ReturnCode;
382static LONG smartcard_ListReadersW_Call(scard_call_context* smartcard,
wStream* out,
387 DWORD cchReaders = 0;
403 WINPR_ASSERT(smartcard);
404 WINPR_ASSERT(operation);
406 call = &operation->call.listReaders;
408 string.bp = call->mszGroups;
409 cchReaders = SCARD_AUTOALLOCATE;
410 status = ret.ReturnCode = wrap(smartcard, SCardListReadersW, operation->hContext,
string.wz,
411 (LPWSTR)&mszReaders.pw, &cchReaders);
412 if (status == SCARD_S_SUCCESS)
414 if (cchReaders == SCARD_AUTOALLOCATE)
415 status = SCARD_F_UNKNOWN_ERROR;
418 if (status != SCARD_S_SUCCESS)
420 (void)scard_log_status_error_wlog(smartcard->log,
"SCardListReadersW", status);
421 return smartcard_pack_list_readers_return(out, &ret, TRUE);
424 cchReaders = filter_device_by_name_w(smartcard->names, &mszReaders.pw, cchReaders);
425 ret.msz = mszReaders.pb;
426 ret.cBytes = cchReaders *
sizeof(WCHAR);
427 status = smartcard_pack_list_readers_return(out, &ret, TRUE);
430 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaders.pb);
432 if (status != SCARD_S_SUCCESS)
435 return ret.ReturnCode;
438static LONG smartcard_IntroduceReaderGroupA_Call(scard_call_context* smartcard,
439 WINPR_ATTR_UNUSED
wStream* out,
445 WINPR_ASSERT(smartcard);
447 WINPR_ASSERT(operation);
449 call = &operation->call.contextAndStringA;
450 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupA, operation->hContext, call->sz);
451 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderGroupA", ret.ReturnCode);
452 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderGroupA");
453 return ret.ReturnCode;
456static LONG smartcard_IntroduceReaderGroupW_Call(scard_call_context* smartcard,
457 WINPR_ATTR_UNUSED
wStream* out,
463 WINPR_ASSERT(smartcard);
465 WINPR_ASSERT(operation);
467 call = &operation->call.contextAndStringW;
468 ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupW, operation->hContext, call->sz);
469 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderGroupW", ret.ReturnCode);
470 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderGroupW");
471 return ret.ReturnCode;
474static LONG smartcard_IntroduceReaderA_Call(scard_call_context* smartcard,
475 WINPR_ATTR_UNUSED
wStream* out,
481 WINPR_ASSERT(smartcard);
483 WINPR_ASSERT(operation);
485 call = &operation->call.contextAndTwoStringA;
487 wrap(smartcard, SCardIntroduceReaderA, operation->hContext, call->sz1, call->sz2);
488 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderA", ret.ReturnCode);
489 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderA");
490 return ret.ReturnCode;
493static LONG smartcard_IntroduceReaderW_Call(scard_call_context* smartcard,
494 WINPR_ATTR_UNUSED
wStream* out,
500 WINPR_ASSERT(smartcard);
502 WINPR_ASSERT(operation);
504 call = &operation->call.contextAndTwoStringW;
506 wrap(smartcard, SCardIntroduceReaderW, operation->hContext, call->sz1, call->sz2);
507 scard_log_status_error_wlog(smartcard->log,
"SCardIntroduceReaderW", ret.ReturnCode);
508 smartcard_trace_long_return_int(smartcard->log, &ret,
"IntroduceReaderW");
509 return ret.ReturnCode;
512static LONG smartcard_ForgetReaderA_Call(scard_call_context* smartcard,
513 WINPR_ATTR_UNUSED
wStream* out,
519 WINPR_ASSERT(smartcard);
521 WINPR_ASSERT(operation);
523 call = &operation->call.contextAndStringA;
524 ret.ReturnCode = wrap(smartcard, SCardForgetReaderA, operation->hContext, call->sz);
525 scard_log_status_error_wlog(smartcard->log,
"SCardForgetReaderA", ret.ReturnCode);
526 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardForgetReaderA");
527 return ret.ReturnCode;
530static LONG smartcard_ForgetReaderW_Call(scard_call_context* smartcard,
531 WINPR_ATTR_UNUSED
wStream* out,
537 WINPR_ASSERT(smartcard);
539 WINPR_ASSERT(operation);
541 call = &operation->call.contextAndStringW;
542 ret.ReturnCode = wrap(smartcard, SCardForgetReaderW, operation->hContext, call->sz);
543 scard_log_status_error_wlog(smartcard->log,
"SCardForgetReaderW", ret.ReturnCode);
544 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardForgetReaderW");
545 return ret.ReturnCode;
548static LONG smartcard_AddReaderToGroupA_Call(scard_call_context* smartcard,
549 WINPR_ATTR_UNUSED
wStream* out,
555 WINPR_ASSERT(smartcard);
557 WINPR_ASSERT(operation);
559 call = &operation->call.contextAndTwoStringA;
561 wrap(smartcard, SCardAddReaderToGroupA, operation->hContext, call->sz1, call->sz2);
562 scard_log_status_error_wlog(smartcard->log,
"SCardAddReaderToGroupA", ret.ReturnCode);
563 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardAddReaderToGroupA");
564 return ret.ReturnCode;
567static LONG smartcard_AddReaderToGroupW_Call(scard_call_context* smartcard,
568 WINPR_ATTR_UNUSED
wStream* out,
574 WINPR_ASSERT(smartcard);
576 WINPR_ASSERT(operation);
578 call = &operation->call.contextAndTwoStringW;
580 wrap(smartcard, SCardAddReaderToGroupW, operation->hContext, call->sz1, call->sz2);
581 scard_log_status_error_wlog(smartcard->log,
"SCardAddReaderToGroupW", ret.ReturnCode);
582 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardAddReaderToGroupA");
583 return ret.ReturnCode;
586static LONG smartcard_RemoveReaderFromGroupA_Call(scard_call_context* smartcard,
587 WINPR_ATTR_UNUSED
wStream* out,
593 WINPR_ASSERT(smartcard);
595 WINPR_ASSERT(operation);
597 call = &operation->call.contextAndTwoStringA;
599 wrap(smartcard, SCardRemoveReaderFromGroupA, operation->hContext, call->sz1, call->sz2);
600 scard_log_status_error_wlog(smartcard->log,
"SCardRemoveReaderFromGroupA", ret.ReturnCode);
601 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardRemoveReaderFromGroupA");
602 return ret.ReturnCode;
605static LONG smartcard_RemoveReaderFromGroupW_Call(scard_call_context* smartcard,
606 WINPR_ATTR_UNUSED
wStream* out,
612 WINPR_ASSERT(smartcard);
614 WINPR_ASSERT(operation);
616 call = &operation->call.contextAndTwoStringW;
618 wrap(smartcard, SCardRemoveReaderFromGroupW, operation->hContext, call->sz1, call->sz2);
619 scard_log_status_error_wlog(smartcard->log,
"SCardRemoveReaderFromGroupW", ret.ReturnCode);
620 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardRemoveReaderFromGroupW");
621 return ret.ReturnCode;
624static LONG smartcard_LocateCardsA_Call(scard_call_context* smartcard,
wStream* out,
631 WINPR_ASSERT(smartcard);
632 WINPR_ASSERT(operation);
634 call = &operation->call.locateCardsA;
636 ret.ReturnCode = wrap(smartcard, SCardLocateCardsA, operation->hContext, call->mszCards,
637 call->rgReaderStates, call->cReaders);
638 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsA", ret.ReturnCode);
639 ret.cReaders = call->cReaders;
640 ret.rgReaderStates = NULL;
642 if (ret.cReaders > 0)
646 if (!ret.rgReaderStates)
647 return STATUS_NO_MEMORY;
650 for (UINT32 x = 0; x < ret.cReaders; x++)
652 ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
653 ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
654 ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
655 CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
656 sizeof(ret.rgReaderStates[x].rgbAtr));
659 status = smartcard_pack_locate_cards_return(out, &ret);
661 if (status != SCARD_S_SUCCESS)
664 return ret.ReturnCode;
667static LONG smartcard_LocateCardsW_Call(scard_call_context* smartcard,
wStream* out,
674 WINPR_ASSERT(smartcard);
675 WINPR_ASSERT(operation);
677 call = &operation->call.locateCardsW;
679 ret.ReturnCode = wrap(smartcard, SCardLocateCardsW, operation->hContext, call->mszCards,
680 call->rgReaderStates, call->cReaders);
681 scard_log_status_error_wlog(smartcard->log,
"SCardLocateCardsW", ret.ReturnCode);
682 ret.cReaders = call->cReaders;
683 ret.rgReaderStates = NULL;
685 if (ret.cReaders > 0)
689 if (!ret.rgReaderStates)
690 return STATUS_NO_MEMORY;
693 for (UINT32 x = 0; x < ret.cReaders; x++)
695 ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
696 ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
697 ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
698 CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
699 sizeof(ret.rgReaderStates[x].rgbAtr));
702 status = smartcard_pack_locate_cards_return(out, &ret);
704 if (status != SCARD_S_SUCCESS)
707 return ret.ReturnCode;
710static LONG smartcard_ReadCacheA_Call(scard_call_context* smartcard,
wStream* out,
718 WINPR_ASSERT(smartcard);
720 WINPR_ASSERT(operation);
722 call = &operation->call.readCacheA;
723 autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE);
725 if (!call->Common.fPbDataIsNULL)
727 ret.cbDataLen = call->Common.cbDataLen;
730 ret.pbData = malloc(ret.cbDataLen);
732 return SCARD_F_INTERNAL_ERROR;
737 ret.ReturnCode = wrap(smartcard, SCardReadCacheA, operation->hContext,
738 call->Common.CardIdentifier, call->Common.FreshnessCounter,
739 call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
742 wrap(smartcard, SCardReadCacheA, operation->hContext, call->Common.CardIdentifier,
743 call->Common.FreshnessCounter, call->szLookupName, ret.pbData, &ret.cbDataLen);
744 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
745 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
747 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheA", ret.ReturnCode);
750 status = smartcard_pack_read_cache_return(out, &ret);
752 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
755 if (status != SCARD_S_SUCCESS)
758 return ret.ReturnCode;
761static LONG smartcard_ReadCacheW_Call(scard_call_context* smartcard,
wStream* out,
768 WINPR_ASSERT(smartcard);
770 WINPR_ASSERT(operation);
772 call = &operation->call.readCacheW;
774 if (!call->Common.fPbDataIsNULL)
775 ret.cbDataLen = SCARD_AUTOALLOCATE;
778 wrap(smartcard, SCardReadCacheW, operation->hContext, call->Common.CardIdentifier,
779 call->Common.FreshnessCounter, call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
781 if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
782 (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
784 scard_log_status_error_wlog(smartcard->log,
"SCardReadCacheW", ret.ReturnCode);
787 status = smartcard_pack_read_cache_return(out, &ret);
789 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
791 if (status != SCARD_S_SUCCESS)
794 return ret.ReturnCode;
797static LONG smartcard_WriteCacheA_Call(scard_call_context* smartcard,
798 WINPR_ATTR_UNUSED
wStream* out,
804 WINPR_ASSERT(smartcard);
806 WINPR_ASSERT(operation);
808 call = &operation->call.writeCacheA;
810 ret.ReturnCode = wrap(smartcard, SCardWriteCacheA, operation->hContext,
811 call->Common.CardIdentifier, call->Common.FreshnessCounter,
812 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
813 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheA", ret.ReturnCode);
814 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheA");
815 return ret.ReturnCode;
818static LONG smartcard_WriteCacheW_Call(scard_call_context* smartcard,
819 WINPR_ATTR_UNUSED
wStream* out,
825 WINPR_ASSERT(smartcard);
827 WINPR_ASSERT(operation);
829 call = &operation->call.writeCacheW;
831 ret.ReturnCode = wrap(smartcard, SCardWriteCacheW, operation->hContext,
832 call->Common.CardIdentifier, call->Common.FreshnessCounter,
833 call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
834 scard_log_status_error_wlog(smartcard->log,
"SCardWriteCacheW", ret.ReturnCode);
835 smartcard_trace_long_return_int(smartcard->log, &ret,
"SCardWriteCacheW");
836 return ret.ReturnCode;
839static LONG smartcard_GetTransmitCount_Call(scard_call_context* smartcard,
wStream* out,
845 WINPR_ASSERT(smartcard);
847 WINPR_ASSERT(operation);
849 ret.ReturnCode = wrap(smartcard, SCardGetTransmitCount, operation->hCard, &ret.cTransmitCount);
850 scard_log_status_error_wlog(smartcard->log,
"SCardGetTransmitCount", ret.ReturnCode);
851 status = smartcard_pack_get_transmit_count_return(out, &ret);
852 if (status != SCARD_S_SUCCESS)
855 return ret.ReturnCode;
858static LONG smartcard_ReleaseStartedEvent_Call(scard_call_context* smartcard,
wStream* out,
861 WINPR_UNUSED(smartcard);
863 WINPR_UNUSED(operation);
865 WLog_Print(smartcard->log, WLOG_WARN,
866 "According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
867 "this is not supported?!?");
868 return SCARD_E_UNSUPPORTED_FEATURE;
871static LONG smartcard_GetReaderIcon_Call(scard_call_context* smartcard,
wStream* out,
878 WINPR_ASSERT(smartcard);
880 WINPR_ASSERT(operation);
882 call = &operation->call.getReaderIcon;
884 ret.cbDataLen = SCARD_AUTOALLOCATE;
885 ret.ReturnCode = wrap(smartcard, SCardGetReaderIconW, operation->hContext, call->szReaderName,
886 (LPBYTE)&ret.pbData, &ret.cbDataLen);
887 scard_log_status_error_wlog(smartcard->log,
"SCardGetReaderIconW", ret.ReturnCode);
888 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cbDataLen == SCARD_AUTOALLOCATE))
889 return SCARD_F_UNKNOWN_ERROR;
891 status = smartcard_pack_get_reader_icon_return(out, &ret);
892 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
893 if (status != SCARD_S_SUCCESS)
896 return ret.ReturnCode;
899static LONG smartcard_GetDeviceTypeId_Call(scard_call_context* smartcard,
wStream* out,
906 WINPR_ASSERT(smartcard);
908 WINPR_ASSERT(operation);
910 call = &operation->call.getDeviceTypeId;
912 ret.ReturnCode = wrap(smartcard, SCardGetDeviceTypeIdW, operation->hContext, call->szReaderName,
914 scard_log_status_error_wlog(smartcard->log,
"SCardGetDeviceTypeIdW", ret.ReturnCode);
916 status = smartcard_pack_device_type_id_return(out, &ret);
917 if (status != SCARD_S_SUCCESS)
920 return ret.ReturnCode;
923static LONG smartcard_GetStatusChangeA_Call(scard_call_context* smartcard,
wStream* out,
926 LONG status = STATUS_NO_MEMORY;
928 const DWORD dwTimeStep = 100;
933 WINPR_ASSERT(smartcard);
935 WINPR_ASSERT(operation);
937 call = &operation->call.getStatusChangeA;
938 dwTimeOut = call->dwTimeOut;
940 if (call->cReaders > 0)
942 ret.cReaders = call->cReaders;
945 if (!rgReaderStates || !ret.rgReaderStates)
949 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
951 if (call->cReaders > 0)
952 memcpy(rgReaderStates, call->rgReaderStates,
954 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
955 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
956 if (ret.ReturnCode != SCARD_E_TIMEOUT)
958 if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
960 if (dwTimeOut != INFINITE)
963 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", ret.ReturnCode);
965 for (UINT32 index = 0; index < ret.cReaders; index++)
970 rout->dwCurrentState = cur->dwCurrentState;
971 rout->dwEventState = cur->dwEventState;
972 rout->cbAtr = cur->cbAtr;
973 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
976 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
978 free(ret.rgReaderStates);
979 free(rgReaderStates);
980 if (status != SCARD_S_SUCCESS)
982 return ret.ReturnCode;
985static LONG smartcard_GetStatusChangeW_Call(scard_call_context* smartcard,
wStream* out,
988 LONG status = STATUS_NO_MEMORY;
990 const DWORD dwTimeStep = 100;
994 WINPR_ASSERT(smartcard);
996 WINPR_ASSERT(operation);
999 dwTimeOut = call->dwTimeOut;
1001 if (call->cReaders > 0)
1003 ret.cReaders = call->cReaders;
1006 if (!rgReaderStates || !ret.rgReaderStates)
1010 for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
1012 if (call->cReaders > 0)
1013 memcpy(rgReaderStates, call->rgReaderStates,
1016 ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
1017 MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
1019 if (ret.ReturnCode != SCARD_E_TIMEOUT)
1021 if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
1023 if (dwTimeOut != INFINITE)
1026 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeW", ret.ReturnCode);
1028 for (UINT32 index = 0; index < ret.cReaders; index++)
1033 rout->dwCurrentState = cur->dwCurrentState;
1034 rout->dwEventState = cur->dwEventState;
1035 rout->cbAtr = cur->cbAtr;
1036 CopyMemory(&(rout->rgbAtr), cur->rgbAtr,
sizeof(rout->rgbAtr));
1039 status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
1041 free(ret.rgReaderStates);
1042 free(rgReaderStates);
1043 if (status != SCARD_S_SUCCESS)
1045 return ret.ReturnCode;
1048static LONG smartcard_Cancel_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1053 WINPR_ASSERT(smartcard);
1055 WINPR_ASSERT(operation);
1057 ret.ReturnCode = wrap(smartcard, SCardCancel, operation->hContext);
1058 scard_log_status_error_wlog(smartcard->log,
"SCardCancel", ret.ReturnCode);
1059 smartcard_trace_long_return_int(smartcard->log, &ret,
"Cancel");
1060 return ret.ReturnCode;
1063static LONG smartcard_ConnectA_Call(scard_call_context* smartcard,
wStream* out,
1067 SCARDHANDLE hCard = 0;
1071 WINPR_ASSERT(smartcard);
1073 WINPR_ASSERT(operation);
1075 call = &operation->call.connectA;
1077 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1078 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1080 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1083 ret.ReturnCode = wrap(smartcard, SCardConnectA, operation->hContext, (
char*)call->szReader,
1084 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1085 &ret.dwActiveProtocol);
1086 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1087 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1089 status = smartcard_pack_connect_return(out, &ret);
1090 if (status != SCARD_S_SUCCESS)
1093 status = ret.ReturnCode;
1099static LONG smartcard_ConnectW_Call(scard_call_context* smartcard,
wStream* out,
1103 SCARDHANDLE hCard = 0;
1107 WINPR_ASSERT(smartcard);
1109 WINPR_ASSERT(operation);
1111 call = &operation->call.connectW;
1113 if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1114 (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1116 call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1119 ret.ReturnCode = wrap(smartcard, SCardConnectW, operation->hContext, (WCHAR*)call->szReader,
1120 call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1121 &ret.dwActiveProtocol);
1122 smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1123 smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1125 status = smartcard_pack_connect_return(out, &ret);
1126 if (status != SCARD_S_SUCCESS)
1129 status = ret.ReturnCode;
1135static LONG smartcard_Reconnect_Call(scard_call_context* smartcard,
wStream* out,
1142 WINPR_ASSERT(smartcard);
1144 WINPR_ASSERT(operation);
1146 call = &operation->call.reconnect;
1148 wrap(smartcard, SCardReconnect, operation->hCard, call->dwShareMode,
1149 call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
1150 scard_log_status_error_wlog(smartcard->log,
"SCardReconnect", ret.ReturnCode);
1151 status = smartcard_pack_reconnect_return(out, &ret);
1152 if (status != SCARD_S_SUCCESS)
1155 return ret.ReturnCode;
1158static LONG smartcard_Disconnect_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1164 WINPR_ASSERT(smartcard);
1166 WINPR_ASSERT(operation);
1168 call = &operation->call.hCardAndDisposition;
1170 ret.ReturnCode = wrap(smartcard, SCardDisconnect, operation->hCard, call->dwDisposition);
1171 scard_log_status_error_wlog(smartcard->log,
"SCardDisconnect", ret.ReturnCode);
1172 smartcard_trace_long_return_int(smartcard->log, &ret,
"Disconnect");
1174 return ret.ReturnCode;
1177static LONG smartcard_BeginTransaction_Call(scard_call_context* smartcard,
1178 WINPR_ATTR_UNUSED
wStream* out,
1183 WINPR_ASSERT(smartcard);
1185 WINPR_ASSERT(operation);
1187 ret.ReturnCode = wrap(smartcard, SCardBeginTransaction, operation->hCard);
1188 scard_log_status_error_wlog(smartcard->log,
"SCardBeginTransaction", ret.ReturnCode);
1189 smartcard_trace_long_return_int(smartcard->log, &ret,
"BeginTransaction");
1190 return ret.ReturnCode;
1193static LONG smartcard_EndTransaction_Call(scard_call_context* smartcard,
1194 WINPR_ATTR_UNUSED
wStream* out,
1200 WINPR_ASSERT(smartcard);
1202 WINPR_ASSERT(operation);
1204 call = &operation->call.hCardAndDisposition;
1206 ret.ReturnCode = wrap(smartcard, SCardEndTransaction, operation->hCard, call->dwDisposition);
1207 scard_log_status_error_wlog(smartcard->log,
"SCardEndTransaction", ret.ReturnCode);
1208 smartcard_trace_long_return_int(smartcard->log, &ret,
"EndTransaction");
1209 return ret.ReturnCode;
1212static LONG smartcard_State_Call(scard_call_context* smartcard,
wStream* out,
1218 WINPR_ASSERT(smartcard);
1220 WINPR_ASSERT(operation);
1222 ret.cbAtrLen = SCARD_ATR_LENGTH;
1223 ret.ReturnCode = wrap(smartcard, SCardState, operation->hCard, &ret.dwState, &ret.dwProtocol,
1224 (BYTE*)&ret.rgAtr, &ret.cbAtrLen);
1226 scard_log_status_error_wlog(smartcard->log,
"SCardState", ret.ReturnCode);
1227 status = smartcard_pack_state_return(out, &ret);
1228 if (status != SCARD_S_SUCCESS)
1231 return ret.ReturnCode;
1234static LONG smartcard_StatusA_Call(scard_call_context* smartcard,
wStream* out,
1239 DWORD cchReaderLen = 0;
1241 LPSTR mszReaderNames = NULL;
1244 WINPR_ASSERT(smartcard);
1246 WINPR_ASSERT(operation);
1248 call = &operation->call.status;
1250 call->cbAtrLen = 32;
1251 cbAtrLen = call->cbAtrLen;
1253 if (call->fmszReaderNamesIsNULL)
1256 cchReaderLen = SCARD_AUTOALLOCATE;
1258 status = ret.ReturnCode =
1259 wrap(smartcard, SCardStatusA, operation->hCard,
1260 call->fmszReaderNamesIsNULL ? NULL : (LPSTR)&mszReaderNames, &cchReaderLen,
1261 &ret.dwState, &ret.dwProtocol, cbAtrLen ? (BYTE*)&ret.pbAtr : NULL, &cbAtrLen);
1263 scard_log_status_error_wlog(smartcard->log,
"SCardStatusA", status);
1264 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cchReaderLen == SCARD_AUTOALLOCATE))
1265 return SCARD_F_UNKNOWN_ERROR;
1267 if (status == SCARD_S_SUCCESS)
1269 if (!call->fmszReaderNamesIsNULL)
1270 ret.mszReaderNames = (BYTE*)mszReaderNames;
1272 ret.cBytes = cchReaderLen;
1275 ret.cbAtrLen = cbAtrLen;
1278 status = smartcard_pack_status_return(out, &ret, FALSE);
1281 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1283 if (status != SCARD_S_SUCCESS)
1285 return ret.ReturnCode;
1288static LONG smartcard_StatusW_Call(scard_call_context* smartcard,
wStream* out,
1293 LPWSTR mszReaderNames = NULL;
1297 WINPR_ASSERT(smartcard);
1299 WINPR_ASSERT(operation);
1301 call = &operation->call.status;
1307 cbAtrLen = call->cbAtrLen = 32;
1309 if (call->fmszReaderNamesIsNULL)
1312 ret.cBytes = SCARD_AUTOALLOCATE;
1314 status = ret.ReturnCode =
1315 wrap(smartcard, SCardStatusW, operation->hCard,
1316 call->fmszReaderNamesIsNULL ? NULL : (LPWSTR)&mszReaderNames, &ret.cBytes,
1317 &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
1318 scard_log_status_error_wlog(smartcard->log,
"SCardStatusW", status);
1319 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (ret.cBytes == SCARD_AUTOALLOCATE))
1320 return SCARD_F_UNKNOWN_ERROR;
1322 if (status == SCARD_S_SUCCESS)
1324 if (!call->fmszReaderNamesIsNULL)
1325 ret.mszReaderNames = (BYTE*)mszReaderNames;
1327 ret.cbAtrLen = cbAtrLen;
1331 WINPR_ASSERT(ret.cBytes < SCARD_AUTOALLOCATE /
sizeof(WCHAR));
1332 const size_t blen =
sizeof(WCHAR) * ret.cBytes;
1333 WINPR_ASSERT(blen <= UINT32_MAX);
1334 ret.cBytes = (UINT32)blen;
1336 status = smartcard_pack_status_return(out, &ret, TRUE);
1337 if (status != SCARD_S_SUCCESS)
1341 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1343 return ret.ReturnCode;
1346static LONG smartcard_Transmit_Call(scard_call_context* smartcard,
wStream* out,
1353 WINPR_ASSERT(smartcard);
1355 WINPR_ASSERT(operation);
1357 call = &operation->call.transmit;
1358 ret.cbRecvLength = 0;
1359 ret.pbRecvBuffer = NULL;
1361 if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
1363 if (call->cbRecvLength >= 66560)
1364 call->cbRecvLength = 66560;
1366 ret.cbRecvLength = call->cbRecvLength;
1367 ret.pbRecvBuffer = (BYTE*)malloc(ret.cbRecvLength);
1369 if (!ret.pbRecvBuffer)
1370 return STATUS_NO_MEMORY;
1373 ret.pioRecvPci = call->pioRecvPci;
1375 wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
1376 call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
1378 scard_log_status_error_wlog(smartcard->log,
"SCardTransmit", ret.ReturnCode);
1380 status = smartcard_pack_transmit_return(out, &ret);
1381 free(ret.pbRecvBuffer);
1383 if (status != SCARD_S_SUCCESS)
1385 return ret.ReturnCode;
1388static LONG smartcard_Control_Call(scard_call_context* smartcard,
wStream* out,
1395 WINPR_ASSERT(smartcard);
1397 WINPR_ASSERT(operation);
1399 call = &operation->call.control;
1400 ret.cbOutBufferSize = call->cbOutBufferSize;
1401 ret.pvOutBuffer = (BYTE*)malloc(call->cbOutBufferSize);
1403 if (!ret.pvOutBuffer)
1404 return SCARD_E_NO_MEMORY;
1407 wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
1408 call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
1409 scard_log_status_error_wlog(smartcard->log,
"SCardControl", ret.ReturnCode);
1410 status = smartcard_pack_control_return(out, &ret);
1412 free(ret.pvOutBuffer);
1413 if (status != SCARD_S_SUCCESS)
1415 return ret.ReturnCode;
1418static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard,
wStream* out,
1421 BOOL autoAllocate = FALSE;
1423 DWORD cbAttrLen = 0;
1424 LPBYTE pbAttr = NULL;
1428 WINPR_ASSERT(smartcard);
1429 WINPR_ASSERT(operation);
1431 call = &operation->call.getAttrib;
1433 if (!call->fpbAttrIsNULL)
1435 autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE) ? TRUE : FALSE;
1436 cbAttrLen = call->cbAttrLen;
1437 if (cbAttrLen && !autoAllocate)
1439 ret.pbAttr = (BYTE*)malloc(cbAttrLen);
1442 return SCARD_E_NO_MEMORY;
1445 pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
1449 wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
1450 scard_log_status_error_wlog(smartcard->log,
"SCardGetAttrib", ret.ReturnCode);
1451 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cbAttrLen == SCARD_AUTOALLOCATE))
1452 return SCARD_F_UNKNOWN_ERROR;
1454 ret.cbAttrLen = cbAttrLen;
1456 status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
1459 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
1465static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED
wStream* out,
1471 WINPR_ASSERT(smartcard);
1473 WINPR_ASSERT(operation);
1475 call = &operation->call.setAttrib;
1477 ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
1479 scard_log_status_error_wlog(smartcard->log,
"SCardSetAttrib", ret.ReturnCode);
1480 smartcard_trace_long_return_int(smartcard->log, &ret,
"SetAttrib");
1482 return ret.ReturnCode;
1485static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard,
1486 WINPR_ATTR_UNUSED
wStream* out,
1489 LONG status = SCARD_S_SUCCESS;
1491 WINPR_ASSERT(smartcard);
1493 WINPR_UNUSED(operation);
1495 if (!smartcard->StartedEvent)
1496 smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
1498 if (!smartcard->StartedEvent)
1499 status = SCARD_E_NO_SERVICE;
1504static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard,
wStream* out,
1512 WINPR_ASSERT(smartcard);
1513 WINPR_ASSERT(operation);
1515 call = &operation->call.locateCardsByATRA;
1519 return STATUS_NO_MEMORY;
1521 for (UINT32 i = 0; i < call->cReaders; i++)
1524 state->szReader = call->rgReaderStates[i].szReader;
1525 state->dwCurrentState = call->rgReaderStates[i].dwCurrentState;
1526 state->dwEventState = call->rgReaderStates[i].dwEventState;
1527 state->cbAtr = call->rgReaderStates[i].cbAtr;
1528 CopyMemory(&(state->rgbAtr), &(call->rgReaderStates[i].rgbAtr), 36);
1531 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1532 0x000001F4, states, call->cReaders);
1534 scard_log_status_error_wlog(smartcard->log,
"SCardGetStatusChangeA", status);
1535 for (UINT32 i = 0; i < call->cAtrs; i++)
1537 for (UINT32 j = 0; j < call->cReaders; j++)
1539 for (UINT32 k = 0; k < call->rgAtrMasks[i].cbAtr; k++)
1541 if ((call->rgAtrMasks[i].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]) !=
1542 (states[j].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]))
1547 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1552 ret.cReaders = call->cReaders;
1553 ret.rgReaderStates = NULL;
1555 if (ret.cReaders > 0)
1558 if (!ret.rgReaderStates)
1561 return STATUS_NO_MEMORY;
1564 for (UINT32 i = 0; i < ret.cReaders; i++)
1567 ret.rgReaderStates[i].dwCurrentState = state->dwCurrentState;
1568 ret.rgReaderStates[i].dwEventState = state->dwEventState;
1569 ret.rgReaderStates[i].cbAtr = state->cbAtr;
1570 CopyMemory(&(ret.rgReaderStates[i].rgbAtr), &(state->rgbAtr),
1571 sizeof(ret.rgReaderStates[i].rgbAtr));
1576 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1578 free(ret.rgReaderStates);
1579 if (status != SCARD_S_SUCCESS)
1581 return ret.ReturnCode;
1584LONG smartcard_irp_device_control_call(scard_call_context* smartcard,
wStream* out,
1589 size_t objectBufferLength = 0;
1591 WINPR_ASSERT(smartcard);
1593 WINPR_ASSERT(pIoStatus);
1594 WINPR_ASSERT(operation);
1596 const UINT32 ioControlCode = operation->ioControlCode;
1604 const size_t outMaxLen = MAX(2048, operation->outputBufferLength);
1605 if (!Stream_EnsureRemainingCapacity(out, outMaxLen))
1606 return SCARD_E_NO_MEMORY;
1609 Stream_Write_UINT32(out, 0);
1610 Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH);
1611 Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH);
1612 Stream_Write_UINT32(out, 0);
1615 switch (ioControlCode)
1617 case SCARD_IOCTL_ESTABLISHCONTEXT:
1618 result = smartcard_EstablishContext_Call(smartcard, out, operation);
1621 case SCARD_IOCTL_RELEASECONTEXT:
1622 result = smartcard_ReleaseContext_Call(smartcard, out, operation);
1625 case SCARD_IOCTL_ISVALIDCONTEXT:
1626 result = smartcard_IsValidContext_Call(smartcard, out, operation);
1629 case SCARD_IOCTL_LISTREADERGROUPSA:
1630 result = smartcard_ListReaderGroupsA_Call(smartcard, out, operation);
1633 case SCARD_IOCTL_LISTREADERGROUPSW:
1634 result = smartcard_ListReaderGroupsW_Call(smartcard, out, operation);
1637 case SCARD_IOCTL_LISTREADERSA:
1638 result = smartcard_ListReadersA_Call(smartcard, out, operation);
1641 case SCARD_IOCTL_LISTREADERSW:
1642 result = smartcard_ListReadersW_Call(smartcard, out, operation);
1645 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1646 result = smartcard_IntroduceReaderGroupA_Call(smartcard, out, operation);
1649 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1650 result = smartcard_IntroduceReaderGroupW_Call(smartcard, out, operation);
1653 case SCARD_IOCTL_FORGETREADERGROUPA:
1654 result = smartcard_ForgetReaderA_Call(smartcard, out, operation);
1657 case SCARD_IOCTL_FORGETREADERGROUPW:
1658 result = smartcard_ForgetReaderW_Call(smartcard, out, operation);
1661 case SCARD_IOCTL_INTRODUCEREADERA:
1662 result = smartcard_IntroduceReaderA_Call(smartcard, out, operation);
1665 case SCARD_IOCTL_INTRODUCEREADERW:
1666 result = smartcard_IntroduceReaderW_Call(smartcard, out, operation);
1669 case SCARD_IOCTL_FORGETREADERA:
1670 result = smartcard_ForgetReaderA_Call(smartcard, out, operation);
1673 case SCARD_IOCTL_FORGETREADERW:
1674 result = smartcard_ForgetReaderW_Call(smartcard, out, operation);
1677 case SCARD_IOCTL_ADDREADERTOGROUPA:
1678 result = smartcard_AddReaderToGroupA_Call(smartcard, out, operation);
1681 case SCARD_IOCTL_ADDREADERTOGROUPW:
1682 result = smartcard_AddReaderToGroupW_Call(smartcard, out, operation);
1685 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1686 result = smartcard_RemoveReaderFromGroupA_Call(smartcard, out, operation);
1689 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1690 result = smartcard_RemoveReaderFromGroupW_Call(smartcard, out, operation);
1693 case SCARD_IOCTL_LOCATECARDSA:
1694 result = smartcard_LocateCardsA_Call(smartcard, out, operation);
1697 case SCARD_IOCTL_LOCATECARDSW:
1698 result = smartcard_LocateCardsW_Call(smartcard, out, operation);
1701 case SCARD_IOCTL_GETSTATUSCHANGEA:
1702 result = smartcard_GetStatusChangeA_Call(smartcard, out, operation);
1705 case SCARD_IOCTL_GETSTATUSCHANGEW:
1706 result = smartcard_GetStatusChangeW_Call(smartcard, out, operation);
1709 case SCARD_IOCTL_CANCEL:
1710 result = smartcard_Cancel_Call(smartcard, out, operation);
1713 case SCARD_IOCTL_CONNECTA:
1714 result = smartcard_ConnectA_Call(smartcard, out, operation);
1717 case SCARD_IOCTL_CONNECTW:
1718 result = smartcard_ConnectW_Call(smartcard, out, operation);
1721 case SCARD_IOCTL_RECONNECT:
1722 result = smartcard_Reconnect_Call(smartcard, out, operation);
1725 case SCARD_IOCTL_DISCONNECT:
1726 result = smartcard_Disconnect_Call(smartcard, out, operation);
1729 case SCARD_IOCTL_BEGINTRANSACTION:
1730 result = smartcard_BeginTransaction_Call(smartcard, out, operation);
1733 case SCARD_IOCTL_ENDTRANSACTION:
1734 result = smartcard_EndTransaction_Call(smartcard, out, operation);
1737 case SCARD_IOCTL_STATE:
1738 result = smartcard_State_Call(smartcard, out, operation);
1741 case SCARD_IOCTL_STATUSA:
1742 result = smartcard_StatusA_Call(smartcard, out, operation);
1745 case SCARD_IOCTL_STATUSW:
1746 result = smartcard_StatusW_Call(smartcard, out, operation);
1749 case SCARD_IOCTL_TRANSMIT:
1750 result = smartcard_Transmit_Call(smartcard, out, operation);
1753 case SCARD_IOCTL_CONTROL:
1754 result = smartcard_Control_Call(smartcard, out, operation);
1757 case SCARD_IOCTL_GETATTRIB:
1758 result = smartcard_GetAttrib_Call(smartcard, out, operation);
1761 case SCARD_IOCTL_SETATTRIB:
1762 result = smartcard_SetAttrib_Call(smartcard, out, operation);
1765 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
1766 result = smartcard_AccessStartedEvent_Call(smartcard, out, operation);
1769 case SCARD_IOCTL_LOCATECARDSBYATRA:
1770 result = smartcard_LocateCardsByATRA_Call(smartcard, out, operation);
1773 case SCARD_IOCTL_LOCATECARDSBYATRW:
1774 result = smartcard_LocateCardsW_Call(smartcard, out, operation);
1777 case SCARD_IOCTL_READCACHEA:
1778 result = smartcard_ReadCacheA_Call(smartcard, out, operation);
1781 case SCARD_IOCTL_READCACHEW:
1782 result = smartcard_ReadCacheW_Call(smartcard, out, operation);
1785 case SCARD_IOCTL_WRITECACHEA:
1786 result = smartcard_WriteCacheA_Call(smartcard, out, operation);
1789 case SCARD_IOCTL_WRITECACHEW:
1790 result = smartcard_WriteCacheW_Call(smartcard, out, operation);
1793 case SCARD_IOCTL_GETTRANSMITCOUNT:
1794 result = smartcard_GetTransmitCount_Call(smartcard, out, operation);
1797 case SCARD_IOCTL_RELEASETARTEDEVENT:
1798 result = smartcard_ReleaseStartedEvent_Call(smartcard, out, operation);
1801 case SCARD_IOCTL_GETREADERICON:
1802 result = smartcard_GetReaderIcon_Call(smartcard, out, operation);
1805 case SCARD_IOCTL_GETDEVICETYPEID:
1806 result = smartcard_GetDeviceTypeId_Call(smartcard, out, operation);
1810 result = STATUS_UNSUCCESSFUL;
1820 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
1821 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
1823 offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
1824 smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
1827 if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
1828 (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
1829 (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
1831 WLog_Print(smartcard->log, WLOG_WARN,
1832 "IRP failure: %s (0x%08" PRIX32
"), status: %s (0x%08" PRIX32
")",
1833 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
1834 SCardGetErrorString(result), result);
1837 *pIoStatus = STATUS_SUCCESS;
1839 if ((result & 0xC0000000L) == 0xC0000000L)
1842 *pIoStatus = result;
1843 WLog_Print(smartcard->log, WLOG_WARN,
1844 "IRP failure: %s (0x%08" PRIX32
"), ntstatus: 0x%08" PRIX32
"",
1845 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, result);
1848 Stream_SealLength(out);
1849 size_t outputBufferLength = Stream_Length(out);
1850 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1851 outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1852 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1853 objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
1854 WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
1855 WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
1856 Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1865 if (outputBufferLength > operation->outputBufferLength)
1867 WLog_Print(smartcard->log, WLOG_WARN,
1868 "IRP warn: expected outputBufferLength %" PRIu32
", but current limit %" PRIu32
1869 ", respond with STATUS_BUFFER_TOO_SMALL",
1870 operation->outputBufferLength, outputBufferLength);
1872 *pIoStatus = STATUS_BUFFER_TOO_SMALL;
1873 result = *pIoStatus;
1874 outputBufferLength = 0;
1875 objectBufferLength = 0;
1879 Stream_Write_UINT32(out, (UINT32)outputBufferLength);
1880 smartcard_pack_common_type_header(out);
1881 smartcard_pack_private_type_header(
1882 out, (UINT32)objectBufferLength);
1883 Stream_Write_INT32(out, result);
1884 Stream_SetPosition(out, Stream_Length(out));
1885 return SCARD_S_SUCCESS;
1888void context_free(
void* arg)
1890 struct s_scard_context_element* element = arg;
1894 if (element->fn_free)
1895 element->fn_free(element->context);
1899scard_call_context* smartcard_call_context_new(
const rdpSettings* settings)
1902 scard_call_context* ctx = NULL;
1904 WINPR_ASSERT(settings);
1905 ctx = calloc(1,
sizeof(scard_call_context));
1909 ctx->log = WLog_Get(SCARD_TAG);
1910 WINPR_ASSERT(ctx->log);
1912 ctx->stopEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
1913 if (!ctx->stopEvent)
1916 ctx->names = LinkedList_New();
1920#if defined(WITH_SMARTCARD_EMULATE)
1924 if (ctx->useEmulatedCard)
1926#if defined(WITH_SMARTCARD_EMULATE)
1927 ctx->emulation = Emulate_New(settings);
1928 if (!ctx->emulation)
1931 WLog_Print(ctx->log, WLOG_ERROR,
"Smartcard emulation requested, but not supported!");
1940 ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
1942 if (!ctx->hWinSCardLibrary)
1944 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard library: '%s'",
1949 if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
1951 ctx->pWinSCardApi = &ctx->WinSCardApi;
1955 ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
1958 if (!ctx->pWinSCardApi)
1960 WLog_Print(ctx->log, WLOG_ERROR,
"Failed to load WinSCard API!");
1965 ctx->rgSCardContextList = HashTable_New(FALSE);
1966 if (!ctx->rgSCardContextList)
1969 obj = HashTable_ValueObject(ctx->rgSCardContextList);
1971 obj->fnObjectFree = context_free;
1975 WINPR_PRAGMA_DIAG_PUSH
1976 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1977 smartcard_call_context_free(ctx);
1978 WINPR_PRAGMA_DIAG_POP
1982void smartcard_call_context_free(scard_call_context* ctx)
1987 smartcard_call_context_signal_stop(ctx, FALSE);
1989 LinkedList_Free(ctx->names);
1990 if (ctx->StartedEvent)
1992 WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
1993 wrap(ctx, SCardReleaseStartedEvent);
1996 if (ctx->useEmulatedCard)
1998#ifdef WITH_SMARTCARD_EMULATE
2001 Emulate_Free(ctx->emulation);
2002 ctx->emulation = NULL;
2007 if (ctx->hWinSCardLibrary)
2010 FreeLibrary(ctx->hWinSCardLibrary);
2011 ctx->hWinSCardLibrary = NULL;
2014 ctx->pWinSCardApi = NULL;
2016 HashTable_Free(ctx->rgSCardContextList);
2017 (void)CloseHandle(ctx->stopEvent);
2021BOOL smartcard_call_context_add(scard_call_context* ctx,
const char* name)
2025 return LinkedList_AddLast(ctx->names, name);
2028BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2031 if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
2033 wrap(ctx, SCardCancel, hContext);
2038BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2041 wrap(ctx, SCardReleaseContext, hContext);
2045BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
2049 HashTable_Clear(ctx->rgSCardContextList);
2053BOOL smarcard_call_set_callbacks(scard_call_context* ctx,
void* userdata,
2054 void* (*fn_new)(
void*, SCARDCONTEXT),
void (*fn_free)(
void*))
2057 ctx->userdata = userdata;
2058 ctx->fn_new = fn_new;
2059 ctx->fn_free = fn_free;
2063void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2065 struct s_scard_context_element* element = NULL;
2068 element = HashTable_GetItemValue(ctx->rgSCardContextList, (
void*)hContext);
2071 return element->context;
2074BOOL smartcard_call_is_configured(scard_call_context* ctx)
2078#if defined(WITH_SMARTCARD_EMULATE)
2079 if (ctx->useEmulatedCard)
2080 return Emulate_IsConfigured(ctx->emulation);
2086BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
2089 if (!ctx->stopEvent)
2093 return ResetEvent(ctx->stopEvent);
2095 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.