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;
 
 1323  if (status == SCARD_S_SUCCESS)
 
 1325    if (!call->fmszReaderNamesIsNULL)
 
 1326      ret.mszReaderNames = (BYTE*)mszReaderNames;
 
 1328    ret.cbAtrLen = cbAtrLen;
 
 1331  if (ret.cBytes != SCARD_AUTOALLOCATE)
 
 1334    WINPR_ASSERT(ret.cBytes < SCARD_AUTOALLOCATE / 
sizeof(WCHAR));
 
 1335    blen = 
sizeof(WCHAR) * ret.cBytes;
 
 1336    WINPR_ASSERT(blen <= UINT32_MAX);
 
 1337    ret.cBytes = (UINT32)blen;
 
 1340  status = smartcard_pack_status_return(out, &ret, TRUE);
 
 1341  if (status != SCARD_S_SUCCESS)
 
 1345    wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
 
 1347  return ret.ReturnCode;
 
 1350static LONG smartcard_Transmit_Call(scard_call_context* smartcard, 
wStream* out,
 
 1357  WINPR_ASSERT(smartcard);
 
 1359  WINPR_ASSERT(operation);
 
 1361  call = &operation->call.transmit;
 
 1362  ret.cbRecvLength = 0;
 
 1363  ret.pbRecvBuffer = NULL;
 
 1365  if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
 
 1367    if (call->cbRecvLength >= 66560)
 
 1368      call->cbRecvLength = 66560;
 
 1370    ret.cbRecvLength = call->cbRecvLength;
 
 1371    ret.pbRecvBuffer = (BYTE*)malloc(ret.cbRecvLength);
 
 1373    if (!ret.pbRecvBuffer)
 
 1374      return STATUS_NO_MEMORY;
 
 1377  ret.pioRecvPci = call->pioRecvPci;
 
 1379      wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
 
 1380           call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
 
 1382  scard_log_status_error_wlog(smartcard->log, 
"SCardTransmit", ret.ReturnCode);
 
 1384  status = smartcard_pack_transmit_return(out, &ret);
 
 1385  free(ret.pbRecvBuffer);
 
 1387  if (status != SCARD_S_SUCCESS)
 
 1389  return ret.ReturnCode;
 
 1392static LONG smartcard_Control_Call(scard_call_context* smartcard, 
wStream* out,
 
 1399  WINPR_ASSERT(smartcard);
 
 1401  WINPR_ASSERT(operation);
 
 1403  call = &operation->call.control;
 
 1404  ret.cbOutBufferSize = call->cbOutBufferSize;
 
 1405  ret.pvOutBuffer = (BYTE*)malloc(call->cbOutBufferSize);
 
 1407  if (!ret.pvOutBuffer)
 
 1408    return SCARD_E_NO_MEMORY;
 
 1411      wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
 
 1412           call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
 
 1413  scard_log_status_error_wlog(smartcard->log, 
"SCardControl", ret.ReturnCode);
 
 1414  status = smartcard_pack_control_return(out, &ret);
 
 1416  free(ret.pvOutBuffer);
 
 1417  if (status != SCARD_S_SUCCESS)
 
 1419  return ret.ReturnCode;
 
 1422static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard, 
wStream* out,
 
 1425  BOOL autoAllocate = FALSE;
 
 1427  DWORD cbAttrLen = 0;
 
 1428  LPBYTE pbAttr = NULL;
 
 1432  WINPR_ASSERT(smartcard);
 
 1433  WINPR_ASSERT(operation);
 
 1435  call = &operation->call.getAttrib;
 
 1437  if (!call->fpbAttrIsNULL)
 
 1439    autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE) ? TRUE : FALSE;
 
 1440    cbAttrLen = call->cbAttrLen;
 
 1441    if (cbAttrLen && !autoAllocate)
 
 1443      ret.pbAttr = (BYTE*)malloc(cbAttrLen);
 
 1446        return SCARD_E_NO_MEMORY;
 
 1449    pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
 
 1453      wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
 
 1454  scard_log_status_error_wlog(smartcard->log, 
"SCardGetAttrib", ret.ReturnCode);
 
 1455  if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cbAttrLen == SCARD_AUTOALLOCATE))
 
 1456    return SCARD_F_UNKNOWN_ERROR;
 
 1458  ret.cbAttrLen = cbAttrLen;
 
 1460  status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
 
 1463    wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
 
 1469static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED 
wStream* out,
 
 1475  WINPR_ASSERT(smartcard);
 
 1477  WINPR_ASSERT(operation);
 
 1479  call = &operation->call.setAttrib;
 
 1481  ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
 
 1483  scard_log_status_error_wlog(smartcard->log, 
"SCardSetAttrib", ret.ReturnCode);
 
 1484  smartcard_trace_long_return_int(smartcard->log, &ret, 
"SetAttrib");
 
 1486  return ret.ReturnCode;
 
 1489static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard,
 
 1490                                              WINPR_ATTR_UNUSED 
wStream* out,
 
 1493  LONG status = SCARD_S_SUCCESS;
 
 1495  WINPR_ASSERT(smartcard);
 
 1497  WINPR_UNUSED(operation);
 
 1499  if (!smartcard->StartedEvent)
 
 1500    smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
 
 1502  if (!smartcard->StartedEvent)
 
 1503    status = SCARD_E_NO_SERVICE;
 
 1508static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard, 
wStream* out,
 
 1516  WINPR_ASSERT(smartcard);
 
 1517  WINPR_ASSERT(operation);
 
 1519  call = &operation->call.locateCardsByATRA;
 
 1523    return STATUS_NO_MEMORY;
 
 1525  for (UINT32 i = 0; i < call->cReaders; i++)
 
 1528    state->szReader = call->rgReaderStates[i].szReader;
 
 1529    state->dwCurrentState = call->rgReaderStates[i].dwCurrentState;
 
 1530    state->dwEventState = call->rgReaderStates[i].dwEventState;
 
 1531    state->cbAtr = call->rgReaderStates[i].cbAtr;
 
 1532    CopyMemory(&(state->rgbAtr), &(call->rgReaderStates[i].rgbAtr), 36);
 
 1535  status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
 
 1536                                 0x000001F4, states, call->cReaders);
 
 1538  scard_log_status_error_wlog(smartcard->log, 
"SCardGetStatusChangeA", status);
 
 1539  for (UINT32 i = 0; i < call->cAtrs; i++)
 
 1541    for (UINT32 j = 0; j < call->cReaders; j++)
 
 1543      for (UINT32 k = 0; k < call->rgAtrMasks[i].cbAtr; k++)
 
 1545        if ((call->rgAtrMasks[i].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]) !=
 
 1546            (states[j].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]))
 
 1551        states[j].dwEventState |= SCARD_STATE_ATRMATCH;
 
 1556  ret.cReaders = call->cReaders;
 
 1557  ret.rgReaderStates = NULL;
 
 1559  if (ret.cReaders > 0)
 
 1562  if (!ret.rgReaderStates)
 
 1565    return STATUS_NO_MEMORY;
 
 1568  for (UINT32 i = 0; i < ret.cReaders; i++)
 
 1571    ret.rgReaderStates[i].dwCurrentState = state->dwCurrentState;
 
 1572    ret.rgReaderStates[i].dwEventState = state->dwEventState;
 
 1573    ret.rgReaderStates[i].cbAtr = state->cbAtr;
 
 1574    CopyMemory(&(ret.rgReaderStates[i].rgbAtr), &(state->rgbAtr),
 
 1575               sizeof(ret.rgReaderStates[i].rgbAtr));
 
 1580  status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
 
 1582  free(ret.rgReaderStates);
 
 1583  if (status != SCARD_S_SUCCESS)
 
 1585  return ret.ReturnCode;
 
 1588LONG smartcard_irp_device_control_call(scard_call_context* smartcard, 
wStream* out,
 
 1593  size_t objectBufferLength = 0;
 
 1595  WINPR_ASSERT(smartcard);
 
 1597  WINPR_ASSERT(pIoStatus);
 
 1598  WINPR_ASSERT(operation);
 
 1600  const UINT32 ioControlCode = operation->ioControlCode;
 
 1608  const size_t outMaxLen = MAX(2048, operation->outputBufferLength);
 
 1609  if (!Stream_EnsureRemainingCapacity(out, outMaxLen))
 
 1610    return SCARD_E_NO_MEMORY;
 
 1613  Stream_Write_UINT32(out, 0);                            
 
 1614  Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH);  
 
 1615  Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH); 
 
 1616  Stream_Write_UINT32(out, 0);                            
 
 1619  switch (ioControlCode)
 
 1621    case SCARD_IOCTL_ESTABLISHCONTEXT:
 
 1622      result = smartcard_EstablishContext_Call(smartcard, out, operation);
 
 1625    case SCARD_IOCTL_RELEASECONTEXT:
 
 1626      result = smartcard_ReleaseContext_Call(smartcard, out, operation);
 
 1629    case SCARD_IOCTL_ISVALIDCONTEXT:
 
 1630      result = smartcard_IsValidContext_Call(smartcard, out, operation);
 
 1633    case SCARD_IOCTL_LISTREADERGROUPSA:
 
 1634      result = smartcard_ListReaderGroupsA_Call(smartcard, out, operation);
 
 1637    case SCARD_IOCTL_LISTREADERGROUPSW:
 
 1638      result = smartcard_ListReaderGroupsW_Call(smartcard, out, operation);
 
 1641    case SCARD_IOCTL_LISTREADERSA:
 
 1642      result = smartcard_ListReadersA_Call(smartcard, out, operation);
 
 1645    case SCARD_IOCTL_LISTREADERSW:
 
 1646      result = smartcard_ListReadersW_Call(smartcard, out, operation);
 
 1649    case SCARD_IOCTL_INTRODUCEREADERGROUPA:
 
 1650      result = smartcard_IntroduceReaderGroupA_Call(smartcard, out, operation);
 
 1653    case SCARD_IOCTL_INTRODUCEREADERGROUPW:
 
 1654      result = smartcard_IntroduceReaderGroupW_Call(smartcard, out, operation);
 
 1657    case SCARD_IOCTL_FORGETREADERGROUPA:
 
 1658      result = smartcard_ForgetReaderA_Call(smartcard, out, operation);
 
 1661    case SCARD_IOCTL_FORGETREADERGROUPW:
 
 1662      result = smartcard_ForgetReaderW_Call(smartcard, out, operation);
 
 1665    case SCARD_IOCTL_INTRODUCEREADERA:
 
 1666      result = smartcard_IntroduceReaderA_Call(smartcard, out, operation);
 
 1669    case SCARD_IOCTL_INTRODUCEREADERW:
 
 1670      result = smartcard_IntroduceReaderW_Call(smartcard, out, operation);
 
 1673    case SCARD_IOCTL_FORGETREADERA:
 
 1674      result = smartcard_ForgetReaderA_Call(smartcard, out, operation);
 
 1677    case SCARD_IOCTL_FORGETREADERW:
 
 1678      result = smartcard_ForgetReaderW_Call(smartcard, out, operation);
 
 1681    case SCARD_IOCTL_ADDREADERTOGROUPA:
 
 1682      result = smartcard_AddReaderToGroupA_Call(smartcard, out, operation);
 
 1685    case SCARD_IOCTL_ADDREADERTOGROUPW:
 
 1686      result = smartcard_AddReaderToGroupW_Call(smartcard, out, operation);
 
 1689    case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
 
 1690      result = smartcard_RemoveReaderFromGroupA_Call(smartcard, out, operation);
 
 1693    case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
 
 1694      result = smartcard_RemoveReaderFromGroupW_Call(smartcard, out, operation);
 
 1697    case SCARD_IOCTL_LOCATECARDSA:
 
 1698      result = smartcard_LocateCardsA_Call(smartcard, out, operation);
 
 1701    case SCARD_IOCTL_LOCATECARDSW:
 
 1702      result = smartcard_LocateCardsW_Call(smartcard, out, operation);
 
 1705    case SCARD_IOCTL_GETSTATUSCHANGEA:
 
 1706      result = smartcard_GetStatusChangeA_Call(smartcard, out, operation);
 
 1709    case SCARD_IOCTL_GETSTATUSCHANGEW:
 
 1710      result = smartcard_GetStatusChangeW_Call(smartcard, out, operation);
 
 1713    case SCARD_IOCTL_CANCEL:
 
 1714      result = smartcard_Cancel_Call(smartcard, out, operation);
 
 1717    case SCARD_IOCTL_CONNECTA:
 
 1718      result = smartcard_ConnectA_Call(smartcard, out, operation);
 
 1721    case SCARD_IOCTL_CONNECTW:
 
 1722      result = smartcard_ConnectW_Call(smartcard, out, operation);
 
 1725    case SCARD_IOCTL_RECONNECT:
 
 1726      result = smartcard_Reconnect_Call(smartcard, out, operation);
 
 1729    case SCARD_IOCTL_DISCONNECT:
 
 1730      result = smartcard_Disconnect_Call(smartcard, out, operation);
 
 1733    case SCARD_IOCTL_BEGINTRANSACTION:
 
 1734      result = smartcard_BeginTransaction_Call(smartcard, out, operation);
 
 1737    case SCARD_IOCTL_ENDTRANSACTION:
 
 1738      result = smartcard_EndTransaction_Call(smartcard, out, operation);
 
 1741    case SCARD_IOCTL_STATE:
 
 1742      result = smartcard_State_Call(smartcard, out, operation);
 
 1745    case SCARD_IOCTL_STATUSA:
 
 1746      result = smartcard_StatusA_Call(smartcard, out, operation);
 
 1749    case SCARD_IOCTL_STATUSW:
 
 1750      result = smartcard_StatusW_Call(smartcard, out, operation);
 
 1753    case SCARD_IOCTL_TRANSMIT:
 
 1754      result = smartcard_Transmit_Call(smartcard, out, operation);
 
 1757    case SCARD_IOCTL_CONTROL:
 
 1758      result = smartcard_Control_Call(smartcard, out, operation);
 
 1761    case SCARD_IOCTL_GETATTRIB:
 
 1762      result = smartcard_GetAttrib_Call(smartcard, out, operation);
 
 1765    case SCARD_IOCTL_SETATTRIB:
 
 1766      result = smartcard_SetAttrib_Call(smartcard, out, operation);
 
 1769    case SCARD_IOCTL_ACCESSSTARTEDEVENT:
 
 1770      result = smartcard_AccessStartedEvent_Call(smartcard, out, operation);
 
 1773    case SCARD_IOCTL_LOCATECARDSBYATRA:
 
 1774      result = smartcard_LocateCardsByATRA_Call(smartcard, out, operation);
 
 1777    case SCARD_IOCTL_LOCATECARDSBYATRW:
 
 1778      result = smartcard_LocateCardsW_Call(smartcard, out, operation);
 
 1781    case SCARD_IOCTL_READCACHEA:
 
 1782      result = smartcard_ReadCacheA_Call(smartcard, out, operation);
 
 1785    case SCARD_IOCTL_READCACHEW:
 
 1786      result = smartcard_ReadCacheW_Call(smartcard, out, operation);
 
 1789    case SCARD_IOCTL_WRITECACHEA:
 
 1790      result = smartcard_WriteCacheA_Call(smartcard, out, operation);
 
 1793    case SCARD_IOCTL_WRITECACHEW:
 
 1794      result = smartcard_WriteCacheW_Call(smartcard, out, operation);
 
 1797    case SCARD_IOCTL_GETTRANSMITCOUNT:
 
 1798      result = smartcard_GetTransmitCount_Call(smartcard, out, operation);
 
 1801    case SCARD_IOCTL_RELEASETARTEDEVENT:
 
 1802      result = smartcard_ReleaseStartedEvent_Call(smartcard, out, operation);
 
 1805    case SCARD_IOCTL_GETREADERICON:
 
 1806      result = smartcard_GetReaderIcon_Call(smartcard, out, operation);
 
 1809    case SCARD_IOCTL_GETDEVICETYPEID:
 
 1810      result = smartcard_GetDeviceTypeId_Call(smartcard, out, operation);
 
 1814      result = STATUS_UNSUCCESSFUL;
 
 1824  if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
 
 1825      (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
 
 1827    offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
 
 1828    smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
 
 1831  if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
 
 1832      (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
 
 1833      (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
 
 1835    WLog_Print(smartcard->log, WLOG_WARN,
 
 1836               "IRP failure: %s (0x%08" PRIX32 
"), status: %s (0x%08" PRIX32 
")",
 
 1837               scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
 
 1838               SCardGetErrorString(result), WINPR_CXX_COMPAT_CAST(UINT32, result));
 
 1841  *pIoStatus = STATUS_SUCCESS;
 
 1843  if ((result & 0xC0000000L) == 0xC0000000L)
 
 1846    *pIoStatus = result;
 
 1847    WLog_Print(smartcard->log, WLOG_WARN,
 
 1848               "IRP failure: %s (0x%08" PRIX32 
"), ntstatus: 0x%08" PRIX32 
"",
 
 1849               scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
 
 1850               WINPR_CXX_COMPAT_CAST(UINT32, result));
 
 1853  Stream_SealLength(out);
 
 1854  size_t outputBufferLength = Stream_Length(out);
 
 1855  WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
 
 1856  outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
 
 1857  WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
 
 1858  objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
 
 1859  WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
 
 1860  WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
 
 1861  Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH);
 
 1870  if (outputBufferLength > operation->outputBufferLength)
 
 1872    WLog_Print(smartcard->log, WLOG_WARN,
 
 1873               "IRP warn: expected outputBufferLength %" PRIu32 
", but current limit %" PRIuz
 
 1874               ", respond with STATUS_BUFFER_TOO_SMALL",
 
 1875               operation->outputBufferLength, outputBufferLength);
 
 1877    *pIoStatus = STATUS_BUFFER_TOO_SMALL;
 
 1878    result = *pIoStatus;
 
 1879    outputBufferLength = 0;
 
 1880    objectBufferLength = 0;
 
 1884  Stream_Write_UINT32(out, (UINT32)outputBufferLength); 
 
 1885  smartcard_pack_common_type_header(out);               
 
 1886  smartcard_pack_private_type_header(
 
 1887      out, (UINT32)objectBufferLength); 
 
 1888  Stream_Write_INT32(out, result);      
 
 1889  Stream_SetPosition(out, Stream_Length(out));
 
 1890  return SCARD_S_SUCCESS;
 
 1893void context_free(
void* arg)
 
 1895  struct s_scard_context_element* element = arg;
 
 1899  if (element->fn_free)
 
 1900    element->fn_free(element->context);
 
 1904scard_call_context* smartcard_call_context_new(
const rdpSettings* settings)
 
 1907  scard_call_context* ctx = NULL;
 
 1909  WINPR_ASSERT(settings);
 
 1910  ctx = calloc(1, 
sizeof(scard_call_context));
 
 1914  ctx->log = WLog_Get(SCARD_TAG);
 
 1915  WINPR_ASSERT(ctx->log);
 
 1917  ctx->stopEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
 
 1918  if (!ctx->stopEvent)
 
 1921  ctx->names = LinkedList_New();
 
 1925#if defined(WITH_SMARTCARD_EMULATE) 
 1929  if (ctx->useEmulatedCard)
 
 1931#if defined(WITH_SMARTCARD_EMULATE) 
 1932    ctx->emulation = Emulate_New(settings);
 
 1933    if (!ctx->emulation)
 
 1936    WLog_Print(ctx->log, WLOG_ERROR, 
"Smartcard emulation requested, but not supported!");
 
 1945      ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
 
 1947      if (!ctx->hWinSCardLibrary)
 
 1949        WLog_Print(ctx->log, WLOG_ERROR, 
"Failed to load WinSCard library: '%s'",
 
 1954      if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
 
 1956      ctx->pWinSCardApi = &ctx->WinSCardApi;
 
 1960      ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
 
 1963    if (!ctx->pWinSCardApi)
 
 1965      WLog_Print(ctx->log, WLOG_ERROR, 
"Failed to load WinSCard API!");
 
 1970  ctx->rgSCardContextList = HashTable_New(FALSE);
 
 1971  if (!ctx->rgSCardContextList)
 
 1974  obj = HashTable_ValueObject(ctx->rgSCardContextList);
 
 1976  obj->fnObjectFree = context_free;
 
 1980  WINPR_PRAGMA_DIAG_PUSH
 
 1981  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
 
 1982  smartcard_call_context_free(ctx);
 
 1983  WINPR_PRAGMA_DIAG_POP
 
 1987void smartcard_call_context_free(scard_call_context* ctx)
 
 1992  smartcard_call_context_signal_stop(ctx, FALSE);
 
 1994  LinkedList_Free(ctx->names);
 
 1995  if (ctx->StartedEvent)
 
 1997    WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
 
 1998    wrap(ctx, SCardReleaseStartedEvent);
 
 2001  if (ctx->useEmulatedCard)
 
 2003#ifdef WITH_SMARTCARD_EMULATE 
 2006      Emulate_Free(ctx->emulation);
 
 2007      ctx->emulation = NULL;
 
 2012  if (ctx->hWinSCardLibrary)
 
 2015    FreeLibrary(ctx->hWinSCardLibrary);
 
 2016    ctx->hWinSCardLibrary = NULL;
 
 2019  ctx->pWinSCardApi = NULL;
 
 2021  HashTable_Free(ctx->rgSCardContextList);
 
 2022  (void)CloseHandle(ctx->stopEvent);
 
 2026BOOL smartcard_call_context_add(scard_call_context* ctx, 
const char* name)
 
 2030  return LinkedList_AddLast(ctx->names, name);
 
 2033BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
 
 2036  if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
 
 2038    wrap(ctx, SCardCancel, hContext);
 
 2043BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
 
 2046  wrap(ctx, SCardReleaseContext, hContext);
 
 2050BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
 
 2054  HashTable_Clear(ctx->rgSCardContextList);
 
 2058BOOL smarcard_call_set_callbacks(scard_call_context* ctx, 
void* userdata,
 
 2059                                 void* (*fn_new)(
void*, SCARDCONTEXT), 
void (*fn_free)(
void*))
 
 2062  ctx->userdata = userdata;
 
 2063  ctx->fn_new = fn_new;
 
 2064  ctx->fn_free = fn_free;
 
 2068void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
 
 2070  struct s_scard_context_element* element = NULL;
 
 2073  element = HashTable_GetItemValue(ctx->rgSCardContextList, (
void*)hContext);
 
 2076  return element->context;
 
 2079BOOL smartcard_call_is_configured(scard_call_context* ctx)
 
 2083#if defined(WITH_SMARTCARD_EMULATE) 
 2084  if (ctx->useEmulatedCard)
 
 2085    return Emulate_IsConfigured(ctx->emulation);
 
 2091BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
 
 2094  if (!ctx->stopEvent)
 
 2098    return ResetEvent(ctx->stopEvent);
 
 2100    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.