FreeRDP
smartcard_emulate.c
1 
21 #include <freerdp/config.h>
22 #include <freerdp/freerdp.h>
23 
24 #include <winpr/crt.h>
25 #include <winpr/wlog.h>
26 #include <winpr/file.h>
27 #include <winpr/path.h>
28 #include <winpr/library.h>
29 #include <winpr/smartcard.h>
30 #include <winpr/collections.h>
31 #include <winpr/crypto.h>
32 
33 #include <freerdp/emulate/scard/smartcard_emulate.h>
34 #include "FreeRDP.ico.h"
35 
36 #include "smartcard_virtual_gids.h"
37 
38 #define MAX_CACHE_ITEM_SIZE 4096
39 #define MAX_CACHE_ITEM_VALUES 4096
40 
41 static CHAR g_ReaderNameA[] = { 'F', 'r', 'e', 'e', 'R', 'D', 'P', ' ', 'E',
42  'm', 'u', 'l', 'a', 't', 'o', 'r', '\0', '\0' };
43 static INIT_ONCE g_ReaderNameWGuard = INIT_ONCE_STATIC_INIT;
44 static WCHAR g_ReaderNameW[32] = { 0 };
45 static size_t g_ReaderNameWLen = 0;
46 
47 static char* card_id_and_name_a(const UUID* CardIdentifier, LPCSTR LookupName)
48 {
49  WINPR_ASSERT(CardIdentifier);
50  WINPR_ASSERT(LookupName);
51 
52  size_t len = strlen(LookupName) + 34;
53  char* id = malloc(len);
54  if (!id)
55  return NULL;
56 
57  (void)snprintf(id, len, "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X\\%s",
58  CardIdentifier->Data1, CardIdentifier->Data2, CardIdentifier->Data3,
59  CardIdentifier->Data4[0], CardIdentifier->Data4[1], CardIdentifier->Data4[2],
60  CardIdentifier->Data4[3], CardIdentifier->Data4[4], CardIdentifier->Data4[5],
61  CardIdentifier->Data4[6], CardIdentifier->Data4[7], LookupName);
62  return id;
63 }
64 
65 static char* card_id_and_name_w(const UUID* CardIdentifier, LPCWSTR LookupName)
66 {
67  char* res = NULL;
68  char* tmp = ConvertWCharToUtf8Alloc(LookupName, NULL);
69  if (!tmp)
70  return NULL;
71  res = card_id_and_name_a(CardIdentifier, tmp);
72  free(tmp);
73  return res;
74 }
75 
76 static BOOL CALLBACK g_ReaderNameWInit(PINIT_ONCE InitOnce, PVOID Parameter, PVOID* Context)
77 {
78  WINPR_UNUSED(InitOnce);
79  WINPR_UNUSED(Parameter);
80  WINPR_UNUSED(Context);
81  InitializeConstWCharFromUtf8(g_ReaderNameA, g_ReaderNameW, ARRAYSIZE(g_ReaderNameW));
82  g_ReaderNameWLen = _wcsnlen(g_ReaderNameW, ARRAYSIZE(g_ReaderNameW) - 2) + 2;
83  return TRUE;
84 }
85 
86 struct smartcard_emulation_context
87 {
88  const rdpSettings* settings;
89  DWORD log_default_level;
90  wLog* log;
91  wHashTable* contexts;
92  wHashTable* handles;
93  BOOL configured;
94  const char* pem;
95  const char* key;
96  const char* pin;
97 };
98 
99 #define MAX_EMULATED_READERS 1
100 typedef struct
101 {
102  ULONG readerState;
103  SCARD_READERSTATEA readerStateA[MAX_EMULATED_READERS];
104  SCARD_READERSTATEW readerStateW[MAX_EMULATED_READERS];
105  wHashTable* cards;
106  wArrayList* strings;
107  wHashTable* cache;
108  BOOL canceled;
109 } SCardContext;
110 
111 typedef struct
112 {
113  union
114  {
115  void* pv;
116  CHAR* pc;
117  WCHAR* pw;
118  } szReader;
119  BOOL unicode;
120  BOOL transaction;
121  DWORD transmitcount;
122  DWORD dwShareMode;
123  DWORD dwActiveProtocol;
124  SCARDCONTEXT hContext;
125  SCARDHANDLE card;
126  vgidsContext* vgids;
127  size_t referencecount;
128 } SCardHandle;
129 
130 typedef struct
131 {
132  DWORD freshness;
133  DWORD size;
134  char data[MAX_CACHE_ITEM_SIZE];
135 } SCardCacheItem;
136 
137 static SCardHandle* find_reader(SmartcardEmulationContext* smartcard, const void* szReader,
138  BOOL unicode);
139 
140 static const BYTE ATR[] = { 0x3b, 0xf7, 0x18, 0x00, 0x00, 0x80, 0x31, 0xfe, 0x45,
141  0x73, 0x66, 0x74, 0x65, 0x2d, 0x6e, 0x66, 0xc4 };
142 
143 static BOOL scard_status_transition(SCardContext* context)
144 {
145  WINPR_ASSERT(context);
146 
147  switch (context->readerState)
148  {
149  default:
150  case 0:
151  {
152  SCARD_READERSTATEA* reader = &context->readerStateA[0];
153  reader->szReader = g_ReaderNameA;
154  reader->dwEventState = SCARD_STATE_PRESENT;
155  reader->cbAtr = sizeof(ATR);
156  memcpy(reader->rgbAtr, ATR, sizeof(ATR));
157  }
158  {
159  InitOnceExecuteOnce(&g_ReaderNameWGuard, g_ReaderNameWInit, NULL, NULL);
160  SCARD_READERSTATEW* reader = &context->readerStateW[0];
161  reader->szReader = g_ReaderNameW;
162  reader->dwEventState = SCARD_STATE_PRESENT;
163  reader->cbAtr = sizeof(ATR);
164  memcpy(reader->rgbAtr, ATR, sizeof(ATR));
165  }
166  context->readerState = 42;
167  break;
168  }
169 
170  return TRUE;
171 }
172 
173 static UINT32 scard_copy_strings(SCardContext* ctx, void* dst, size_t dstSize, const void* src,
174  size_t srcSize)
175 {
176  WINPR_ASSERT(ctx);
177  WINPR_ASSERT(dst);
178 
179  WINPR_ASSERT(srcSize <= UINT32_MAX);
180  WINPR_ASSERT(dstSize <= UINT32_MAX);
181 
182  if (dstSize == SCARD_AUTOALLOCATE)
183  {
184  void* tmp = malloc(srcSize);
185  memcpy(tmp, src, srcSize);
186  ArrayList_Append(ctx->strings, tmp);
187  *((void**)dst) = tmp;
188  return (UINT32)srcSize;
189  }
190  else
191  {
192  const size_t min = MIN(dstSize, srcSize);
193  memcpy(dst, src, min);
194  return (UINT32)min;
195  }
196 }
197 
198 static void scard_context_free(void* context)
199 {
200  SCardContext* ctx = context;
201  if (ctx)
202  {
203  HashTable_Free(ctx->cards);
204  ArrayList_Free(ctx->strings);
205  HashTable_Free(ctx->cache);
206  }
207  free(ctx);
208 }
209 
210 static SCardContext* scard_context_new(void)
211 {
212  SCardContext* ctx = calloc(1, sizeof(SCardContext));
213  if (!ctx)
214  return NULL;
215 
216  ctx->strings = ArrayList_New(FALSE);
217  if (!ctx->strings)
218  goto fail;
219  else
220  {
221  wObject* obj = ArrayList_Object(ctx->strings);
222  WINPR_ASSERT(obj);
223  obj->fnObjectFree = free;
224  }
225 
226  ctx->cache = HashTable_New(FALSE);
227  if (!ctx->cache)
228  goto fail;
229  if (!HashTable_SetupForStringData(ctx->cache, FALSE))
230  goto fail;
231  else
232  {
233  wObject* val = HashTable_ValueObject(ctx->cache);
234  WINPR_ASSERT(val);
235  val->fnObjectFree = free;
236  }
237 
238  scard_status_transition(ctx);
239  return ctx;
240 fail:
241  scard_context_free(ctx);
242  return NULL;
243 }
244 
245 static void scard_handle_free(void* handle)
246 {
247  SCardHandle* hdl = handle;
248  if (hdl)
249  {
250  free(hdl->szReader.pv);
251  vgids_free(hdl->vgids);
252  }
253  free(hdl);
254 }
255 
256 static SCardHandle* scard_handle_new(SmartcardEmulationContext* smartcard, SCARDCONTEXT context,
257  const void* name, BOOL unicode)
258 {
259  SCardHandle* hdl = NULL;
260 
261  WINPR_ASSERT(smartcard);
262 
263  hdl = calloc(1, sizeof(SCardHandle));
264  if (!hdl)
265  goto fail;
266 
267  /* ATTENTION: Do not use _strdup or _wcsdup!
268  * These strings are required to be double NULL terminated!
269  */
270  if (unicode)
271  {
272  size_t s = _wcslen(name);
273 
274  hdl->szReader.pw = calloc(s + 2, sizeof(WCHAR));
275  if (!hdl->szReader.pw)
276  goto fail;
277  memcpy(hdl->szReader.pv, name, s * sizeof(WCHAR));
278  }
279  else
280  {
281  size_t s = strlen(name);
282 
283  hdl->szReader.pc = calloc(s + 2, sizeof(CHAR));
284  if (!hdl->szReader.pc)
285  goto fail;
286  memcpy(hdl->szReader.pv, name, s * sizeof(CHAR));
287  }
288 
289  if (!hdl->szReader.pv)
290  goto fail;
291 
292  hdl->vgids = vgids_new();
293  if (!hdl->vgids)
294  goto fail;
295 
296  {
297  const char* pem =
298  freerdp_settings_get_string(smartcard->settings, FreeRDP_SmartcardCertificate);
299  const char* key =
300  freerdp_settings_get_string(smartcard->settings, FreeRDP_SmartcardPrivateKey);
301 
302  const char* pin = freerdp_settings_get_string(smartcard->settings, FreeRDP_Password);
303 
304  if (!vgids_init(hdl->vgids, pem, key, pin))
305  goto fail;
306  }
307 
308  hdl->unicode = unicode;
309  hdl->hContext = context;
310  return hdl;
311 
312 fail:
313  scard_handle_free(hdl);
314  return NULL;
315 }
316 
317 static LONG scard_handle_valid(SmartcardEmulationContext* smartcard, SCARDHANDLE handle)
318 {
319  SCardHandle* ctx = NULL;
320 
321  WINPR_ASSERT(smartcard);
322 
323  ctx = HashTable_GetItemValue(smartcard->handles, (const void*)handle);
324  if (!ctx)
325  return SCARD_E_INVALID_HANDLE;
326 
327  return SCARD_S_SUCCESS;
328 }
329 
330 static LONG scard_reader_name_valid_a(SmartcardEmulationContext* smartcard, SCARDCONTEXT context,
331  const char* name)
332 {
333  SCardContext* ctx = NULL;
334 
335  WINPR_ASSERT(smartcard);
336  ctx = HashTable_GetItemValue(smartcard->contexts, (const void*)context);
337 
338  WINPR_ASSERT(name);
339  WINPR_ASSERT(ctx);
340 
341  for (size_t x = 0; x < MAX_EMULATED_READERS; x++)
342  {
343  const SCARD_READERSTATEA* reader = &ctx->readerStateA[x];
344  if (strcmp(reader->szReader, name) == 0)
345  return SCARD_S_SUCCESS;
346  }
347 
348  return SCARD_E_UNKNOWN_READER;
349 }
350 
351 static LONG scard_reader_name_valid_w(SmartcardEmulationContext* smartcard, SCARDCONTEXT context,
352  const WCHAR* name)
353 {
354  SCardContext* ctx = NULL;
355 
356  WINPR_ASSERT(smartcard);
357  ctx = HashTable_GetItemValue(smartcard->contexts, (const void*)context);
358 
359  WINPR_ASSERT(name);
360  WINPR_ASSERT(ctx);
361 
362  for (size_t x = 0; x < MAX_EMULATED_READERS; x++)
363  {
364  const SCARD_READERSTATEW* reader = &ctx->readerStateW[x];
365  if (_wcscmp(reader->szReader, name) == 0)
366  return SCARD_S_SUCCESS;
367  }
368 
369  return SCARD_E_UNKNOWN_READER;
370 }
371 
376 LONG WINAPI Emulate_SCardEstablishContext(SmartcardEmulationContext* smartcard, DWORD dwScope,
377  LPCVOID pvReserved1, LPCVOID pvReserved2,
378  LPSCARDCONTEXT phContext)
379 {
380  LONG status = SCARD_E_NO_MEMORY;
381  SCardContext* ctx = NULL;
382 
383  WINPR_ASSERT(smartcard);
384 
385  ctx = scard_context_new();
386 
387  WINPR_UNUSED(pvReserved1);
388  WINPR_UNUSED(pvReserved2);
389 
390  WLog_Print(smartcard->log, smartcard->log_default_level,
391  "SCardEstablishContext { dwScope: %s (0x%08" PRIX32 ")",
392  SCardGetScopeString(dwScope), dwScope);
393 
394  if (ctx)
395  {
396  SCARDCONTEXT context = { 0 };
397 
398  winpr_RAND(&context, sizeof(SCARDCONTEXT));
399  if (HashTable_Insert(smartcard->contexts, (const void*)context, ctx))
400  {
401  *phContext = context;
402  status = SCARD_S_SUCCESS;
403  }
404  }
405 
406  WLog_Print(smartcard->log, smartcard->log_default_level,
407  "SCardEstablishContext } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
408  status);
409 
410  if (status != SCARD_S_SUCCESS)
411  scard_context_free(ctx);
412  // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): HashTable_Insert takes ownership of ctx
413  return status;
414 }
415 
416 LONG WINAPI Emulate_SCardReleaseContext(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext)
417 {
418  LONG status = 0;
419  SCardContext* value = NULL;
420 
421  WINPR_ASSERT(smartcard);
422 
423  value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
424 
425  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardReleaseContext { hContext: %p",
426  (void*)hContext);
427 
428  if (value)
429  HashTable_Remove(smartcard->contexts, (const void*)hContext);
430 
431  status = SCARD_S_SUCCESS;
432 
433  WLog_Print(smartcard->log, smartcard->log_default_level,
434  "SCardReleaseContext } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
435  status);
436 
437  return status;
438 }
439 
440 LONG WINAPI Emulate_SCardIsValidContext(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext)
441 {
442  LONG status = 0;
443 
444  WINPR_ASSERT(smartcard);
445 
446  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardIsValidContext { hContext: %p",
447  (void*)hContext);
448 
449  status = HashTable_Contains(smartcard->contexts, (const void*)hContext)
450  ? SCARD_S_SUCCESS
451  : SCARD_E_INVALID_HANDLE;
452  if (status == SCARD_S_SUCCESS)
453  {
454  SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
455  WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
456  if (!value)
457  return SCARD_F_INTERNAL_ERROR;
458  }
459 
460  WLog_Print(smartcard->log, smartcard->log_default_level,
461  "SCardIsValidContext } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
462  status);
463 
464  return status;
465 }
466 
467 LONG WINAPI Emulate_SCardListReaderGroupsA(
468  SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
469  LPSTR mszGroups /* NOLINT(readability-non-const-parameter) */, LPDWORD pcchGroups)
470 {
471  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
472 
473  WLog_Print(smartcard->log, smartcard->log_default_level,
474  "SCardListReaderGroupsA { hContext: %p", (void*)hContext);
475 
476  WINPR_UNUSED(mszGroups);
477  WINPR_UNUSED(pcchGroups);
478 
479  /* Not required, return not supported */
480  if (status == SCARD_S_SUCCESS)
481  status = SCARD_E_UNSUPPORTED_FEATURE;
482 
483  WLog_Print(smartcard->log, smartcard->log_default_level,
484  "SCardListReaderGroupsA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
485  status);
486 
487  return status;
488 }
489 
490 LONG WINAPI Emulate_SCardListReaderGroupsW(
491  SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
492  LPWSTR mszGroups /* NOLINT(readability-non-const-parameter) */, LPDWORD pcchGroups)
493 {
494  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
495 
496  WLog_Print(smartcard->log, smartcard->log_default_level,
497  "SCardListReaderGroupsW { hContext: %p", (void*)hContext);
498 
499  WINPR_UNUSED(mszGroups);
500  WINPR_UNUSED(pcchGroups);
501 
502  /* Not required, return not supported */
503  if (status == SCARD_S_SUCCESS)
504  status = SCARD_E_UNSUPPORTED_FEATURE;
505 
506  WLog_Print(smartcard->log, smartcard->log_default_level,
507  "SCardListReaderGroupsW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
508  status);
509 
510  return status;
511 }
512 
513 LONG WINAPI Emulate_SCardListReadersA(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
514  LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
515 {
516  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
517  if (!pcchReaders)
518  status = SCARD_E_INVALID_PARAMETER;
519 
520  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardListReadersA { hContext: %p",
521  (void*)hContext);
522 
523  WINPR_UNUSED(mszGroups); /* Not required */
524 
525  if (SCARD_S_SUCCESS == status)
526  {
527  SCardContext* value =
528  (SCardContext*)HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
529  WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
530 
531  // TODO: If emulator not ready return SCARD_E_NO_READERS_AVAILABLE
532 
533  // TODO: argument mszGrous
534 
535  /* Return length only */
536  if (!mszReaders)
537  *pcchReaders = ARRAYSIZE(g_ReaderNameA);
538  else
539  {
540  *pcchReaders = scard_copy_strings(value, mszReaders, *pcchReaders, g_ReaderNameA,
541  sizeof(g_ReaderNameA));
542  }
543  }
544 
545  WLog_Print(smartcard->log, smartcard->log_default_level,
546  "SCardListReadersA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
547  status);
548 
549  return status;
550 }
551 
552 LONG WINAPI Emulate_SCardListReadersW(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
553  LPCWSTR mszGroups, LPWSTR mszReaders, LPDWORD pcchReaders)
554 {
555  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
556 
557  if (!pcchReaders)
558  status = SCARD_E_INVALID_PARAMETER;
559 
560  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardListReadersW { hContext: %p",
561  (void*)hContext);
562 
563  WINPR_UNUSED(mszGroups); /* Not required */
564 
565  InitOnceExecuteOnce(&g_ReaderNameWGuard, g_ReaderNameWInit, NULL, NULL);
566  if (SCARD_S_SUCCESS == status)
567  {
568  SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
569  WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
570 
571  // TODO: If emulator not ready return SCARD_E_NO_READERS_AVAILABLE
572 
573  // TODO: argument mszGrous
574 
575  /* Return length only */
576  if (!mszReaders)
577  {
578  WINPR_ASSERT(g_ReaderNameWLen <= UINT32_MAX);
579  *pcchReaders = (UINT32)g_ReaderNameWLen;
580  }
581  else
582  {
583  *pcchReaders = scard_copy_strings(value, mszReaders, *pcchReaders, g_ReaderNameW,
584  g_ReaderNameWLen * sizeof(WCHAR)) /
585  sizeof(WCHAR);
586  }
587  }
588 
589  WLog_Print(smartcard->log, smartcard->log_default_level,
590  "SCardListReadersW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
591  status);
592 
593  return status;
594 }
595 
596 LONG WINAPI Emulate_SCardListCardsA(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
597  LPCBYTE pbAtr, LPCGUID rgquidInterfaces,
598  DWORD cguidInterfaceCount,
599  CHAR* mszCards /* NOLINT(readability-non-const-parameter) */,
600  LPDWORD pcchCards /* NOLINT(readability-non-const-parameter) */)
601 {
602  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
603 
604  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardListCardsA { hContext: %p",
605  (void*)hContext);
606 
607  WINPR_UNUSED(pbAtr);
608  WINPR_UNUSED(rgquidInterfaces);
609  WINPR_UNUSED(cguidInterfaceCount);
610  WINPR_UNUSED(mszCards);
611  WINPR_UNUSED(pcchCards);
612 
613  /* Not required, return not supported */
614  if (status == SCARD_S_SUCCESS)
615  status = SCARD_E_UNSUPPORTED_FEATURE;
616 
617  WLog_Print(smartcard->log, smartcard->log_default_level,
618  "SCardListCardsA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
619  status);
620 
621  return status;
622 }
623 
624 LONG WINAPI Emulate_SCardListCardsW(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
625  LPCBYTE pbAtr, LPCGUID rgquidInterfaces,
626  DWORD cguidInterfaceCount,
627  WCHAR* mszCards /* NOLINT(readability-non-const-parameter) */,
628  LPDWORD pcchCards /* NOLINT(readability-non-const-parameter) */)
629 {
630  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
631 
632  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardListCardsW { hContext: %p",
633  (void*)hContext);
634 
635  WINPR_UNUSED(pbAtr);
636  WINPR_UNUSED(rgquidInterfaces);
637  WINPR_UNUSED(cguidInterfaceCount);
638  WINPR_UNUSED(mszCards);
639  WINPR_UNUSED(pcchCards);
640 
641  /* Not required, return not supported */
642  if (status == SCARD_S_SUCCESS)
643  status = SCARD_E_UNSUPPORTED_FEATURE;
644 
645  WLog_Print(smartcard->log, smartcard->log_default_level,
646  "SCardListCardsW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
647  status);
648 
649  return status;
650 }
651 
652 LONG WINAPI Emulate_SCardListInterfacesA(
653  SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext, LPCSTR szCard,
654  LPGUID pguidInterfaces, LPDWORD pcguidInterfaces /* NOLINT(readability-non-const-parameter) */)
655 {
656  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
657 
658  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardListInterfacesA { hContext: %p",
659  (void*)hContext);
660 
661  WINPR_UNUSED(szCard);
662  WINPR_UNUSED(pguidInterfaces);
663  WINPR_UNUSED(pcguidInterfaces);
664 
665  /* Not required, return not supported */
666  if (status == SCARD_S_SUCCESS)
667  status = SCARD_E_UNSUPPORTED_FEATURE;
668 
669  WLog_Print(smartcard->log, smartcard->log_default_level,
670  "SCardListInterfacesA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
671  status);
672 
673  return status;
674 }
675 
676 LONG WINAPI Emulate_SCardListInterfacesW(
677  SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext, LPCWSTR szCard,
678  LPGUID pguidInterfaces, LPDWORD pcguidInterfaces /* NOLINT(readability-non-const-parameter) */)
679 {
680  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
681 
682  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardListInterfacesW { hContext: %p",
683  (void*)hContext);
684 
685  WINPR_UNUSED(szCard);
686  WINPR_UNUSED(pguidInterfaces);
687  WINPR_UNUSED(pcguidInterfaces);
688 
689  /* Not required, return not supported */
690  if (status == SCARD_S_SUCCESS)
691  status = SCARD_E_UNSUPPORTED_FEATURE;
692 
693  WLog_Print(smartcard->log, smartcard->log_default_level,
694  "SCardListInterfacesW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
695  status);
696 
697  return status;
698 }
699 
700 LONG WINAPI Emulate_SCardGetProviderIdA(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
701  LPCSTR szCard, LPGUID pguidProviderId)
702 {
703  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
704 
705  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetProviderIdA { hContext: %p",
706  (void*)hContext);
707 
708  WINPR_UNUSED(szCard);
709  WINPR_UNUSED(pguidProviderId);
710 
711  /* Not required, return not supported */
712  if (status == SCARD_S_SUCCESS)
713  status = SCARD_E_UNSUPPORTED_FEATURE;
714 
715  WLog_Print(smartcard->log, smartcard->log_default_level,
716  "SCardGetProviderIdA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
717  status);
718 
719  return status;
720 }
721 
722 LONG WINAPI Emulate_SCardGetProviderIdW(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
723  LPCWSTR szCard, LPGUID pguidProviderId)
724 {
725  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
726 
727  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetProviderIdW { hContext: %p",
728  (void*)hContext);
729 
730  WINPR_UNUSED(szCard);
731  WINPR_UNUSED(pguidProviderId);
732 
733  /* Not required, return not supported */
734  if (status == SCARD_S_SUCCESS)
735  status = SCARD_E_UNSUPPORTED_FEATURE;
736 
737  WLog_Print(smartcard->log, smartcard->log_default_level,
738  "SCardGetProviderIdW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
739  status);
740 
741  return status;
742 }
743 
744 LONG WINAPI Emulate_SCardGetCardTypeProviderNameA(
745  SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext, LPCSTR szCardName,
746  DWORD dwProviderId, CHAR* szProvider /* NOLINT(readability-non-const-parameter) */,
747  LPDWORD pcchProvider /* NOLINT(readability-non-const-parameter) */)
748 {
749  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
750 
751  WLog_Print(smartcard->log, smartcard->log_default_level,
752  "SCardGetCardTypeProviderNameA { hContext: %p", (void*)hContext);
753 
754  WINPR_UNUSED(szCardName);
755  WINPR_UNUSED(dwProviderId);
756  WINPR_UNUSED(szProvider);
757  WINPR_UNUSED(pcchProvider);
758 
759  /* Not required, return not supported */
760  if (status == SCARD_S_SUCCESS)
761  status = SCARD_E_UNSUPPORTED_FEATURE;
762 
763  WLog_Print(smartcard->log, smartcard->log_default_level,
764  "SCardGetCardTypeProviderNameA } status: %s (0x%08" PRIX32 ")",
765  SCardGetErrorString(status), status);
766 
767  return status;
768 }
769 
770 LONG WINAPI Emulate_SCardGetCardTypeProviderNameW(
771  SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext, LPCWSTR szCardName,
772  DWORD dwProviderId, WCHAR* szProvider /* NOLINT(readability-non-const-parameter) */,
773  LPDWORD pcchProvider /* NOLINT(readability-non-const-parameter) */)
774 {
775  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
776 
777  WLog_Print(smartcard->log, smartcard->log_default_level,
778  "SCardGetCardTypeProviderNameW { hContext: %p", (void*)hContext);
779 
780  WINPR_UNUSED(szCardName);
781  WINPR_UNUSED(dwProviderId);
782  WINPR_UNUSED(szProvider);
783  WINPR_UNUSED(pcchProvider);
784 
785  /* Not required, return not supported */
786  if (status == SCARD_S_SUCCESS)
787  status = SCARD_E_UNSUPPORTED_FEATURE;
788 
789  WLog_Print(smartcard->log, smartcard->log_default_level,
790  "SCardGetCardTypeProviderNameW } status: %s (0x%08" PRIX32 ")",
791  SCardGetErrorString(status), status);
792 
793  return status;
794 }
795 
796 LONG WINAPI Emulate_SCardIntroduceReaderGroupA(SmartcardEmulationContext* smartcard,
797  SCARDCONTEXT hContext, LPCSTR szGroupName)
798 {
799  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
800 
801  WLog_Print(smartcard->log, smartcard->log_default_level,
802  "SCardIntroduceReaderGroupA { hContext: %p", (void*)hContext);
803 
804  WINPR_UNUSED(szGroupName);
805 
806  /* Not required, return not supported */
807  if (status == SCARD_S_SUCCESS)
808  status = SCARD_E_UNSUPPORTED_FEATURE;
809 
810  WLog_Print(smartcard->log, smartcard->log_default_level,
811  "SCardIntroduceReaderGroupA } status: %s (0x%08" PRIX32 ")",
812  SCardGetErrorString(status), status);
813 
814  return status;
815 }
816 
817 LONG WINAPI Emulate_SCardIntroduceReaderGroupW(SmartcardEmulationContext* smartcard,
818  SCARDCONTEXT hContext, LPCWSTR szGroupName)
819 {
820  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
821 
822  WLog_Print(smartcard->log, smartcard->log_default_level,
823  "SCardIntroduceReaderGroupW { hContext: %p", (void*)hContext);
824 
825  WINPR_UNUSED(szGroupName);
826 
827  /* Not required, return not supported */
828  if (status == SCARD_S_SUCCESS)
829  status = SCARD_E_UNSUPPORTED_FEATURE;
830 
831  WLog_Print(smartcard->log, smartcard->log_default_level,
832  "SCardIntroduceReaderGroupW } status: %s (0x%08" PRIX32 ")",
833  SCardGetErrorString(status), status);
834 
835  return status;
836 }
837 
838 LONG WINAPI Emulate_SCardForgetReaderGroupA(SmartcardEmulationContext* smartcard,
839  SCARDCONTEXT hContext, LPCSTR szGroupName)
840 {
841  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
842 
843  WLog_Print(smartcard->log, smartcard->log_default_level,
844  "SCardForgetReaderGroupA { hContext: %p", (void*)hContext);
845 
846  WINPR_UNUSED(szGroupName);
847 
848  /* Not required, return not supported */
849  if (status == SCARD_S_SUCCESS)
850  status = SCARD_E_UNSUPPORTED_FEATURE;
851 
852  WLog_Print(smartcard->log, smartcard->log_default_level,
853  "SCardForgetReaderGroupA } status: %s (0x%08" PRIX32 ")",
854  SCardGetErrorString(status), status);
855 
856  return status;
857 }
858 
859 LONG WINAPI Emulate_SCardForgetReaderGroupW(SmartcardEmulationContext* smartcard,
860  SCARDCONTEXT hContext, LPCWSTR szGroupName)
861 {
862  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
863 
864  WLog_Print(smartcard->log, smartcard->log_default_level,
865  "SCardForgetReaderGroupW { hContext: %p", (void*)hContext);
866 
867  WINPR_UNUSED(szGroupName);
868 
869  /* Not required, return not supported */
870  if (status == SCARD_S_SUCCESS)
871  status = SCARD_E_UNSUPPORTED_FEATURE;
872 
873  WLog_Print(smartcard->log, smartcard->log_default_level,
874  "SCardForgetReaderGroupW } status: %s (0x%08" PRIX32 ")",
875  SCardGetErrorString(status), status);
876 
877  return status;
878 }
879 
880 LONG WINAPI Emulate_SCardIntroduceReaderA(SmartcardEmulationContext* smartcard,
881  SCARDCONTEXT hContext, LPCSTR szReaderName,
882  LPCSTR szDeviceName)
883 {
884  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
885 
886  if (status == SCARD_S_SUCCESS)
887  status = scard_reader_name_valid_a(smartcard, hContext, szReaderName);
888 
889  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardIntroduceReaderA { hContext: %p",
890  (void*)hContext);
891 
892  WINPR_UNUSED(szDeviceName);
893 
894  /* Not required, return not supported */
895  if (status == SCARD_S_SUCCESS)
896  status = SCARD_E_UNSUPPORTED_FEATURE;
897 
898  WLog_Print(smartcard->log, smartcard->log_default_level,
899  "SCardIntroduceReaderA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
900  status);
901 
902  return status;
903 }
904 
905 LONG WINAPI Emulate_SCardIntroduceReaderW(SmartcardEmulationContext* smartcard,
906  SCARDCONTEXT hContext, LPCWSTR szReaderName,
907  LPCWSTR szDeviceName)
908 {
909  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
910 
911  if (status == SCARD_S_SUCCESS)
912  status = scard_reader_name_valid_w(smartcard, hContext, szReaderName);
913 
914  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardIntroduceReaderW { hContext: %p",
915  (void*)hContext);
916 
917  WINPR_UNUSED(szDeviceName);
918 
919  /* Not required, return not supported */
920  if (status == SCARD_S_SUCCESS)
921  status = SCARD_E_UNSUPPORTED_FEATURE;
922 
923  WLog_Print(smartcard->log, smartcard->log_default_level,
924  "SCardIntroduceReaderW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
925  status);
926 
927  return status;
928 }
929 
930 LONG WINAPI Emulate_SCardForgetReaderA(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
931  LPCSTR szReaderName)
932 {
933  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
934 
935  if (status == SCARD_S_SUCCESS)
936  status = scard_reader_name_valid_a(smartcard, hContext, szReaderName);
937 
938  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardForgetReaderA { hContext: %p",
939  (void*)hContext);
940 
941  /* Not required, return not supported */
942  if (status == SCARD_S_SUCCESS)
943  status = SCARD_E_UNSUPPORTED_FEATURE;
944 
945  WLog_Print(smartcard->log, smartcard->log_default_level,
946  "SCardForgetReaderA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
947  status);
948 
949  return status;
950 }
951 
952 LONG WINAPI Emulate_SCardForgetReaderW(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
953  LPCWSTR szReaderName)
954 {
955  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
956 
957  if (status == SCARD_S_SUCCESS)
958  status = scard_reader_name_valid_w(smartcard, hContext, szReaderName);
959 
960  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardForgetReaderW { hContext: %p",
961  (void*)hContext);
962 
963  /* Not required, return not supported */
964  if (status == SCARD_S_SUCCESS)
965  status = SCARD_E_UNSUPPORTED_FEATURE;
966 
967  WLog_Print(smartcard->log, smartcard->log_default_level,
968  "SCardForgetReaderW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
969  status);
970 
971  return status;
972 }
973 
974 LONG WINAPI Emulate_SCardAddReaderToGroupA(SmartcardEmulationContext* smartcard,
975  SCARDCONTEXT hContext, LPCSTR szReaderName,
976  LPCSTR szGroupName)
977 {
978  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
979 
980  if (status == SCARD_S_SUCCESS)
981  status = scard_reader_name_valid_a(smartcard, hContext, szReaderName);
982 
983  WLog_Print(smartcard->log, smartcard->log_default_level,
984  "SCardAddReaderToGroupA { hContext: %p", (void*)hContext);
985 
986  WINPR_UNUSED(szGroupName);
987 
988  /* Not required, return not supported */
989  if (status == SCARD_S_SUCCESS)
990  status = SCARD_E_UNSUPPORTED_FEATURE;
991 
992  WLog_Print(smartcard->log, smartcard->log_default_level,
993  "SCardAddReaderToGroupA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
994  status);
995 
996  return status;
997 }
998 
999 LONG WINAPI Emulate_SCardAddReaderToGroupW(SmartcardEmulationContext* smartcard,
1000  SCARDCONTEXT hContext, LPCWSTR szReaderName,
1001  LPCWSTR szGroupName)
1002 {
1003  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1004 
1005  if (status == SCARD_S_SUCCESS)
1006  status = scard_reader_name_valid_w(smartcard, hContext, szReaderName);
1007 
1008  WLog_Print(smartcard->log, smartcard->log_default_level,
1009  "SCardAddReaderToGroupW { hContext: %p", (void*)hContext);
1010 
1011  WINPR_UNUSED(szGroupName);
1012 
1013  /* Not required, return not supported */
1014  if (status == SCARD_S_SUCCESS)
1015  status = SCARD_E_UNSUPPORTED_FEATURE;
1016 
1017  WLog_Print(smartcard->log, smartcard->log_default_level,
1018  "SCardAddReaderToGroupW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1019  status);
1020 
1021  return status;
1022 }
1023 
1024 LONG WINAPI Emulate_SCardRemoveReaderFromGroupA(SmartcardEmulationContext* smartcard,
1025  SCARDCONTEXT hContext, LPCSTR szReaderName,
1026  LPCSTR szGroupName)
1027 {
1028  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1029 
1030  if (status == SCARD_S_SUCCESS)
1031  status = scard_reader_name_valid_a(smartcard, hContext, szReaderName);
1032 
1033  WLog_Print(smartcard->log, smartcard->log_default_level,
1034  "SCardRemoveReaderFromGroupA { hContext: %p", (void*)hContext);
1035 
1036  WINPR_UNUSED(szGroupName);
1037 
1038  /* Not required, return not supported */
1039  if (status == SCARD_S_SUCCESS)
1040  status = SCARD_E_UNSUPPORTED_FEATURE;
1041 
1042  WLog_Print(smartcard->log, smartcard->log_default_level,
1043  "SCardRemoveReaderFromGroupA } status: %s (0x%08" PRIX32 ")",
1044  SCardGetErrorString(status), status);
1045 
1046  return status;
1047 }
1048 
1049 LONG WINAPI Emulate_SCardRemoveReaderFromGroupW(SmartcardEmulationContext* smartcard,
1050  SCARDCONTEXT hContext, LPCWSTR szReaderName,
1051  LPCWSTR szGroupName)
1052 {
1053  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1054 
1055  if (status == SCARD_S_SUCCESS)
1056  status = scard_reader_name_valid_w(smartcard, hContext, szReaderName);
1057 
1058  WLog_Print(smartcard->log, smartcard->log_default_level,
1059  "SCardRemoveReaderFromGroupW { hContext: %p", (void*)hContext);
1060 
1061  WINPR_UNUSED(szGroupName);
1062 
1063  /* Not required, return not supported */
1064  if (status == SCARD_S_SUCCESS)
1065  status = SCARD_E_UNSUPPORTED_FEATURE;
1066 
1067  WLog_Print(smartcard->log, smartcard->log_default_level,
1068  "SCardRemoveReaderFromGroupW } status: %s (0x%08" PRIX32 ")",
1069  SCardGetErrorString(status), status);
1070 
1071  return status;
1072 }
1073 
1074 LONG WINAPI Emulate_SCardIntroduceCardTypeA(SmartcardEmulationContext* smartcard,
1075  SCARDCONTEXT hContext, LPCSTR szCardName,
1076  LPCGUID pguidPrimaryProvider, LPCGUID rgguidInterfaces,
1077  DWORD dwInterfaceCount, LPCBYTE pbAtr,
1078  LPCBYTE pbAtrMask, DWORD cbAtrLen)
1079 {
1080  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1081 
1082  WLog_Print(smartcard->log, smartcard->log_default_level,
1083  "SCardIntroduceCardTypeA { hContext: %p", (void*)hContext);
1084 
1085  WINPR_UNUSED(szCardName);
1086  WINPR_UNUSED(pguidPrimaryProvider);
1087  WINPR_UNUSED(rgguidInterfaces);
1088  WINPR_UNUSED(dwInterfaceCount);
1089  WINPR_UNUSED(pbAtr);
1090  WINPR_UNUSED(pbAtrMask);
1091  WINPR_UNUSED(cbAtrLen);
1092 
1093  /* Not required, return not supported */
1094  if (status == SCARD_S_SUCCESS)
1095  status = SCARD_E_UNSUPPORTED_FEATURE;
1096 
1097  WLog_Print(smartcard->log, smartcard->log_default_level,
1098  "SCardIntroduceCardTypeA } status: %s (0x%08" PRIX32 ")",
1099  SCardGetErrorString(status), status);
1100 
1101  return status;
1102 }
1103 
1104 LONG WINAPI Emulate_SCardIntroduceCardTypeW(SmartcardEmulationContext* smartcard,
1105  SCARDCONTEXT hContext, LPCWSTR szCardName,
1106  LPCGUID pguidPrimaryProvider, LPCGUID rgguidInterfaces,
1107  DWORD dwInterfaceCount, LPCBYTE pbAtr,
1108  LPCBYTE pbAtrMask, DWORD cbAtrLen)
1109 {
1110  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1111 
1112  WLog_Print(smartcard->log, smartcard->log_default_level,
1113  "SCardIntroduceCardTypeW { hContext: %p", (void*)hContext);
1114 
1115  WINPR_UNUSED(szCardName);
1116  WINPR_UNUSED(pguidPrimaryProvider);
1117  WINPR_UNUSED(rgguidInterfaces);
1118  WINPR_UNUSED(dwInterfaceCount);
1119  WINPR_UNUSED(pbAtr);
1120  WINPR_UNUSED(pbAtrMask);
1121  WINPR_UNUSED(cbAtrLen);
1122 
1123  /* Not required, return not supported */
1124  if (status == SCARD_S_SUCCESS)
1125  status = SCARD_E_UNSUPPORTED_FEATURE;
1126 
1127  WLog_Print(smartcard->log, smartcard->log_default_level,
1128  "SCardIntroduceCardTypeW } status: %s (0x%08" PRIX32 ")",
1129  SCardGetErrorString(status), status);
1130 
1131  return status;
1132 }
1133 
1134 LONG WINAPI Emulate_SCardSetCardTypeProviderNameA(SmartcardEmulationContext* smartcard,
1135  SCARDCONTEXT hContext, LPCSTR szCardName,
1136  DWORD dwProviderId, LPCSTR szProvider)
1137 {
1138  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1139 
1140  WLog_Print(smartcard->log, smartcard->log_default_level,
1141  "SCardSetCardTypeProviderNameA { hContext: %p", (void*)hContext);
1142 
1143  WINPR_UNUSED(szCardName);
1144  WINPR_UNUSED(dwProviderId);
1145  WINPR_UNUSED(szProvider);
1146 
1147  /* Not required, return not supported */
1148  if (status == SCARD_S_SUCCESS)
1149  status = SCARD_E_UNSUPPORTED_FEATURE;
1150 
1151  WLog_Print(smartcard->log, smartcard->log_default_level,
1152  "SCardSetCardTypeProviderNameA } status: %s (0x%08" PRIX32 ")",
1153  SCardGetErrorString(status), status);
1154 
1155  return status;
1156 }
1157 
1158 LONG WINAPI Emulate_SCardSetCardTypeProviderNameW(SmartcardEmulationContext* smartcard,
1159  SCARDCONTEXT hContext, LPCWSTR szCardName,
1160  DWORD dwProviderId, LPCWSTR szProvider)
1161 {
1162  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1163 
1164  WLog_Print(smartcard->log, smartcard->log_default_level,
1165  "SCardSetCardTypeProviderNameA { hContext: %p", (void*)hContext);
1166 
1167  WINPR_UNUSED(szCardName);
1168  WINPR_UNUSED(dwProviderId);
1169  WINPR_UNUSED(szProvider);
1170 
1171  /* Not required, return not supported */
1172  if (status == SCARD_S_SUCCESS)
1173  status = SCARD_E_UNSUPPORTED_FEATURE;
1174 
1175  WLog_Print(smartcard->log, smartcard->log_default_level,
1176  "SCardSetCardTypeProviderNameW } status: %s (0x%08" PRIX32 ")",
1177  SCardGetErrorString(status), status);
1178 
1179  return status;
1180 }
1181 
1182 LONG WINAPI Emulate_SCardForgetCardTypeA(SmartcardEmulationContext* smartcard,
1183  SCARDCONTEXT hContext, LPCSTR szCardName)
1184 {
1185  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1186 
1187  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardForgetCardTypeA { hContext: %p",
1188  (void*)hContext);
1189 
1190  WINPR_UNUSED(szCardName);
1191 
1192  /* Not required, return not supported */
1193  if (status == SCARD_S_SUCCESS)
1194  status = SCARD_E_UNSUPPORTED_FEATURE;
1195 
1196  WLog_Print(smartcard->log, smartcard->log_default_level,
1197  "SCardForgetCardTypeA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1198  status);
1199 
1200  return status;
1201 }
1202 
1203 LONG WINAPI Emulate_SCardForgetCardTypeW(SmartcardEmulationContext* smartcard,
1204  SCARDCONTEXT hContext, LPCWSTR szCardName)
1205 {
1206  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1207 
1208  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardForgetCardTypeW { hContext: %p",
1209  (void*)hContext);
1210 
1211  WINPR_UNUSED(szCardName);
1212 
1213  /* Not required, return not supported */
1214  if (status == SCARD_S_SUCCESS)
1215  status = SCARD_E_UNSUPPORTED_FEATURE;
1216 
1217  WLog_Print(smartcard->log, smartcard->log_default_level,
1218  "SCardForgetCardTypeW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1219  status);
1220 
1221  return status;
1222 }
1223 
1224 LONG WINAPI Emulate_SCardFreeMemory(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
1225  LPVOID pvMem)
1226 {
1227  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1228 
1229  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardFreeMemory { hContext: %p",
1230  (void*)hContext);
1231 
1232  if (status == SCARD_S_SUCCESS)
1233  {
1234  SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
1235  WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
1236 
1237  ArrayList_Remove(value->strings, pvMem);
1238  }
1239 
1240  WLog_Print(smartcard->log, smartcard->log_default_level,
1241  "SCardFreeMemory } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1242  status);
1243 
1244  return status;
1245 }
1246 
1247 HANDLE WINAPI Emulate_SCardAccessStartedEvent(SmartcardEmulationContext* smartcard)
1248 {
1249  HANDLE hEvent = NULL;
1250 
1251  WINPR_ASSERT(smartcard);
1252 
1253  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardAccessStartedEvent {");
1254 
1255  /* Not required, return random */
1256  winpr_RAND(&hEvent, sizeof(hEvent));
1257 
1258  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardAccessStartedEvent } hEvent: %p",
1259  hEvent);
1260 
1261  return hEvent;
1262 }
1263 
1264 void WINAPI Emulate_SCardReleaseStartedEvent(SmartcardEmulationContext* smartcard)
1265 {
1266  WINPR_ASSERT(smartcard);
1267 
1268  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardReleaseStartedEvent {");
1269 
1270  /* Not required, return not supported */
1271 
1272  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardReleaseStartedEvent }");
1273 }
1274 
1275 LONG WINAPI Emulate_SCardLocateCardsA(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
1276  LPCSTR mszCards, LPSCARD_READERSTATEA rgReaderStates,
1277  DWORD cReaders)
1278 {
1279  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1280 
1281  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardLocateCardsA { hContext: %p",
1282  (void*)hContext);
1283 
1284  WINPR_UNUSED(mszCards);
1285  WINPR_UNUSED(rgReaderStates);
1286  WINPR_UNUSED(cReaders);
1287 
1288  /* Not required, return not supported */
1289  if (status == SCARD_S_SUCCESS)
1290  status = SCARD_E_UNSUPPORTED_FEATURE;
1291 
1292  WLog_Print(smartcard->log, smartcard->log_default_level,
1293  "SCardLocateCardsA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1294  status);
1295 
1296  return status;
1297 }
1298 
1299 LONG WINAPI Emulate_SCardLocateCardsW(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
1300  LPCWSTR mszCards, LPSCARD_READERSTATEW rgReaderStates,
1301  DWORD cReaders)
1302 {
1303  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1304 
1305  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardLocateCardsW { hContext: %p",
1306  (void*)hContext);
1307 
1308  WINPR_UNUSED(mszCards);
1309  WINPR_UNUSED(rgReaderStates);
1310  WINPR_UNUSED(cReaders);
1311 
1312  /* Not required, return not supported */
1313  if (status == SCARD_S_SUCCESS)
1314  status = SCARD_E_UNSUPPORTED_FEATURE;
1315 
1316  WLog_Print(smartcard->log, smartcard->log_default_level,
1317  "SCardLocateCardsW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1318  status);
1319 
1320  return status;
1321 }
1322 
1323 LONG WINAPI Emulate_SCardLocateCardsByATRA(SmartcardEmulationContext* smartcard,
1324  SCARDCONTEXT hContext, LPSCARD_ATRMASK rgAtrMasks,
1325  DWORD cAtrs, LPSCARD_READERSTATEA rgReaderStates,
1326  DWORD cReaders)
1327 {
1328  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1329 
1330  WLog_Print(smartcard->log, smartcard->log_default_level,
1331  "SCardLocateCardsByATRA { hContext: %p", (void*)hContext);
1332 
1333  WINPR_UNUSED(rgAtrMasks);
1334  WINPR_UNUSED(cAtrs);
1335  WINPR_UNUSED(rgReaderStates);
1336  WINPR_UNUSED(cReaders);
1337 
1338  /* Not required, return not supported */
1339  if (status == SCARD_S_SUCCESS)
1340  status = SCARD_E_UNSUPPORTED_FEATURE;
1341 
1342  WLog_Print(smartcard->log, smartcard->log_default_level,
1343  "SCardLocateCardsByATRA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1344  status);
1345 
1346  return status;
1347 }
1348 
1349 LONG WINAPI Emulate_SCardLocateCardsByATRW(SmartcardEmulationContext* smartcard,
1350  SCARDCONTEXT hContext, LPSCARD_ATRMASK rgAtrMasks,
1351  DWORD cAtrs, LPSCARD_READERSTATEW rgReaderStates,
1352  DWORD cReaders)
1353 {
1354  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1355 
1356  WLog_Print(smartcard->log, smartcard->log_default_level,
1357  "SCardLocateCardsByATRW { hContext: %p", (void*)hContext);
1358 
1359  WINPR_UNUSED(rgAtrMasks);
1360  WINPR_UNUSED(cAtrs);
1361  WINPR_UNUSED(rgReaderStates);
1362  WINPR_UNUSED(cReaders);
1363 
1364  /* Not required, return not supported */
1365  if (status == SCARD_S_SUCCESS)
1366  status = SCARD_E_UNSUPPORTED_FEATURE;
1367 
1368  WLog_Print(smartcard->log, smartcard->log_default_level,
1369  "SCardLocateCardsByATRW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1370  status);
1371 
1372  return status;
1373 }
1374 
1375 LONG WINAPI Emulate_SCardGetStatusChangeA(SmartcardEmulationContext* smartcard,
1376  SCARDCONTEXT hContext, DWORD dwTimeout,
1377  LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders)
1378 {
1379  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1380 
1381  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetStatusChangeA { hContext: %p",
1382  (void*)hContext);
1383 
1384  if (status == SCARD_S_SUCCESS)
1385  {
1386  const DWORD diff = 100;
1387  size_t eventCount = 0;
1388  SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
1389  WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
1390 
1391  const freerdp* inst = freerdp_settings_get_pointer(smartcard->settings, FreeRDP_instance);
1392  WINPR_ASSERT(inst);
1393 
1394  status = SCARD_E_TIMEOUT;
1395  do
1396  {
1397  for (size_t x = 0; x < cReaders; x++)
1398  {
1399  LPSCARD_READERSTATEA out = &rgReaderStates[x];
1400 
1401  for (size_t y = 0; y < MAX_EMULATED_READERS; y++)
1402  {
1403  const LPSCARD_READERSTATEA in = &value->readerStateA[y];
1404  if (strcmp(out->szReader, in->szReader) == 0)
1405  {
1406  const SCardHandle* hdl = find_reader(smartcard, in->szReader, FALSE);
1407  out->dwEventState = in->dwEventState;
1408  if (hdl)
1409  {
1410  out->dwEventState |= SCARD_STATE_INUSE;
1411  if (hdl->dwShareMode == SCARD_SHARE_EXCLUSIVE)
1412  out->dwEventState |= SCARD_STATE_EXCLUSIVE;
1413  }
1414 
1415  if ((out->dwEventState & SCARD_STATE_EMPTY) !=
1416  (out->dwCurrentState & SCARD_STATE_EMPTY))
1417  out->dwEventState |= SCARD_STATE_CHANGED;
1418  if ((out->dwEventState & SCARD_STATE_PRESENT) !=
1419  (out->dwCurrentState & SCARD_STATE_PRESENT))
1420  out->dwEventState |= SCARD_STATE_CHANGED;
1421 
1422  out->cbAtr = in->cbAtr;
1423  memcpy(out->rgbAtr, in->rgbAtr, out->cbAtr);
1424  if (out->dwEventState & SCARD_STATE_CHANGED)
1425  eventCount++;
1426  }
1427  }
1428  }
1429  if (value->canceled)
1430  {
1431  status = SCARD_E_CANCELLED;
1432  break;
1433  }
1434  if (eventCount != 0)
1435  {
1436  status = SCARD_S_SUCCESS;
1437  break;
1438  }
1439  Sleep(diff);
1440  if (dwTimeout != INFINITE)
1441  dwTimeout -= MIN(dwTimeout, diff);
1442  if (freerdp_shall_disconnect_context(inst->context))
1443  {
1444  status = SCARD_E_CANCELLED;
1445  break;
1446  }
1447  } while (dwTimeout > 0);
1448  }
1449 
1450  WLog_Print(smartcard->log, smartcard->log_default_level,
1451  "SCardGetStatusChangeA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1452  status);
1453 
1454  return status;
1455 }
1456 
1457 LONG WINAPI Emulate_SCardGetStatusChangeW(SmartcardEmulationContext* smartcard,
1458  SCARDCONTEXT hContext, DWORD dwTimeout,
1459  LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders)
1460 {
1461  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1462 
1463  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetStatusChangeW { hContext: %p",
1464  (void*)hContext);
1465 
1466  if (status == SCARD_S_SUCCESS)
1467  {
1468  const DWORD diff = 100;
1469  size_t eventCount = 0;
1470  SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
1471  WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
1472 
1473  const freerdp* inst = freerdp_settings_get_pointer(smartcard->settings, FreeRDP_instance);
1474  WINPR_ASSERT(inst);
1475 
1476  status = SCARD_E_TIMEOUT;
1477  do
1478  {
1479  for (size_t x = 0; x < cReaders; x++)
1480  {
1481  LPSCARD_READERSTATEW out = &rgReaderStates[x];
1482 
1483  for (size_t y = 0; y < MAX_EMULATED_READERS; y++)
1484  {
1485  const LPSCARD_READERSTATEW in = &value->readerStateW[y];
1486  if (_wcscmp(out->szReader, in->szReader) == 0)
1487  {
1488  const SCardHandle* hdl = find_reader(smartcard, in->szReader, TRUE);
1489  out->dwEventState = in->dwEventState;
1490  if (hdl)
1491  {
1492  out->dwEventState |= SCARD_STATE_INUSE;
1493  if (hdl->dwShareMode == SCARD_SHARE_EXCLUSIVE)
1494  out->dwEventState |= SCARD_STATE_EXCLUSIVE;
1495  }
1496  if ((out->dwEventState & SCARD_STATE_EMPTY) !=
1497  (out->dwCurrentState & SCARD_STATE_EMPTY))
1498  out->dwEventState |= SCARD_STATE_CHANGED;
1499  if ((out->dwEventState & SCARD_STATE_PRESENT) !=
1500  (out->dwCurrentState & SCARD_STATE_PRESENT))
1501  out->dwEventState |= SCARD_STATE_CHANGED;
1502  out->cbAtr = in->cbAtr;
1503  memcpy(out->rgbAtr, in->rgbAtr, out->cbAtr);
1504 
1505  if (out->dwEventState & SCARD_STATE_CHANGED)
1506  eventCount++;
1507  }
1508  }
1509  }
1510  if (value->canceled)
1511  {
1512  status = SCARD_E_CANCELLED;
1513  break;
1514  }
1515  if (eventCount != 0)
1516  {
1517  status = SCARD_S_SUCCESS;
1518  break;
1519  }
1520  Sleep(diff);
1521  if (dwTimeout != INFINITE)
1522  dwTimeout -= MIN(dwTimeout, diff);
1523  if (freerdp_shall_disconnect_context(inst->context))
1524  {
1525  status = SCARD_E_CANCELLED;
1526  break;
1527  }
1528  } while (dwTimeout > 0);
1529  }
1530 
1531  WLog_Print(smartcard->log, smartcard->log_default_level,
1532  "SCardGetStatusChangeW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1533  status);
1534 
1535  return status;
1536 }
1537 
1538 LONG WINAPI Emulate_SCardCancel(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext)
1539 {
1540  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1541 
1542  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardCancel { hContext: %p",
1543  (void*)hContext);
1544 
1545  if (status == SCARD_S_SUCCESS)
1546  {
1547  SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
1548  WINPR_ASSERT(value);
1549  value->canceled = TRUE;
1550  }
1551 
1552  WLog_Print(smartcard->log, smartcard->log_default_level,
1553  "SCardCancel } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
1554 
1555  return status;
1556 }
1557 
1558 SCardHandle* find_reader(SmartcardEmulationContext* smartcard, const void* szReader, BOOL unicode)
1559 {
1560  SCardHandle* hdl = NULL;
1561  UINT_PTR* keys = NULL;
1562  size_t count = 0;
1563 
1564  WINPR_ASSERT(smartcard);
1565  count = HashTable_GetKeys(smartcard->handles, &keys);
1566  for (size_t x = 0; x < count; x++)
1567  {
1568  SCardHandle* cur = HashTable_GetItemValue(smartcard->handles, (const void*)keys[x]);
1569  WINPR_ASSERT(cur);
1570 
1571  if (cur->unicode != unicode)
1572  continue;
1573  if (!unicode && (strcmp(cur->szReader.pc, szReader) != 0))
1574  continue;
1575  if (unicode && (_wcscmp(cur->szReader.pw, szReader) != 0))
1576  continue;
1577  hdl = cur;
1578  break;
1579  }
1580  free(keys);
1581  return hdl;
1582 }
1583 
1584 static SCardHandle* reader2handle(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
1585  const void* szReader, BOOL unicode, DWORD dwShareMode,
1586  SCARDHANDLE* phCard, DWORD dwPreferredProtocols,
1587  LPDWORD pdwActiveProtocol)
1588 {
1589  SCardHandle* hdl = NULL;
1590 
1591  WINPR_ASSERT(phCard);
1592 
1593  *phCard = 0;
1594  if (Emulate_SCardIsValidContext(smartcard, hContext) != SCARD_S_SUCCESS)
1595  return NULL;
1596 
1597  hdl = scard_handle_new(smartcard, hContext, szReader, unicode);
1598  if (hdl)
1599  {
1600  winpr_RAND(&hdl->card, sizeof(hdl->card));
1601  hdl->dwActiveProtocol = SCARD_PROTOCOL_T1;
1602  hdl->dwShareMode = dwShareMode;
1603 
1604  if (!HashTable_Insert(smartcard->handles, (const void*)hdl->card, hdl))
1605  {
1606  scard_handle_free(hdl);
1607  hdl = NULL;
1608  }
1609  else
1610  {
1611  if (pdwActiveProtocol)
1612  {
1613  if ((hdl->dwActiveProtocol & dwPreferredProtocols) == 0)
1614  {
1615  scard_handle_free(hdl);
1616  hdl = NULL;
1617  }
1618  else
1619  *pdwActiveProtocol = hdl->dwActiveProtocol;
1620  }
1621  if (hdl)
1622  {
1623  hdl->referencecount++;
1624  *phCard = hdl->card;
1625  }
1626  }
1627  }
1628  WLog_Print(smartcard->log, smartcard->log_default_level, "{ %p }", (void*)*phCard);
1629  return hdl;
1630 }
1631 
1632 LONG WINAPI Emulate_SCardConnectA(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
1633  LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
1634  LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
1635 {
1636  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1637 
1638  if (!phCard || !pdwActiveProtocol)
1639  status = SCARD_E_INVALID_PARAMETER;
1640 
1641  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardConnectA { hContext: %p",
1642  (void*)hContext);
1643 
1644  if (status == SCARD_S_SUCCESS)
1645  {
1646  if (!reader2handle(smartcard, hContext, szReader, FALSE, dwShareMode, phCard,
1647  dwPreferredProtocols, pdwActiveProtocol))
1648  status = SCARD_E_NO_MEMORY;
1649  }
1650 
1651  WLog_Print(smartcard->log, smartcard->log_default_level,
1652  "SCardConnectA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
1653 
1654  return status;
1655 }
1656 
1657 LONG WINAPI Emulate_SCardConnectW(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
1658  LPCWSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
1659  LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
1660 {
1661  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1662 
1663  if (!phCard || !pdwActiveProtocol)
1664  status = SCARD_E_INVALID_PARAMETER;
1665 
1666  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardConnectW { hContext: %p",
1667  (void*)hContext);
1668 
1669  if (status == SCARD_S_SUCCESS)
1670  {
1671  if (!reader2handle(smartcard, hContext, szReader, TRUE, dwShareMode, phCard,
1672  dwPreferredProtocols, pdwActiveProtocol))
1673  status = SCARD_E_NO_MEMORY;
1674  }
1675 
1676  WLog_Print(smartcard->log, smartcard->log_default_level,
1677  "SCardConnectW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
1678 
1679  return status;
1680 }
1681 
1682 LONG WINAPI Emulate_SCardReconnect(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
1683  DWORD dwShareMode, DWORD dwPreferredProtocols,
1684  DWORD dwInitialization, LPDWORD pdwActiveProtocol)
1685 {
1686  LONG status = scard_handle_valid(smartcard, hCard);
1687 
1688  if (!pdwActiveProtocol)
1689  status = SCARD_E_INVALID_PARAMETER;
1690 
1691  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardReconnect { hCard: %p",
1692  (void*)hCard);
1693 
1694  if (status == SCARD_S_SUCCESS)
1695  {
1696  SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1697  WINPR_ASSERT(hdl);
1698 
1699  // TODO: Implement
1700  hdl->dwShareMode = dwShareMode;
1701  hdl->transaction = FALSE;
1702 
1703  *pdwActiveProtocol = hdl->dwActiveProtocol;
1704  }
1705 
1706  WLog_Print(smartcard->log, smartcard->log_default_level,
1707  "SCardReconnect } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1708  status);
1709 
1710  return status;
1711 }
1712 
1713 LONG WINAPI Emulate_SCardDisconnect(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
1714  DWORD dwDisposition)
1715 {
1716  LONG status = scard_handle_valid(smartcard, hCard);
1717 
1718  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardDisconnect { hCard: %p",
1719  (void*)hCard);
1720 
1721  WINPR_UNUSED(dwDisposition); /* We just ignore this. All return values are static anyway */
1722 
1723  if (status == SCARD_S_SUCCESS)
1724  {
1725  SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1726  WINPR_ASSERT(hdl);
1727 
1728  hdl->referencecount--;
1729  if (hdl->referencecount == 0)
1730  HashTable_Remove(smartcard->handles, (const void*)hCard);
1731  }
1732 
1733  WLog_Print(smartcard->log, smartcard->log_default_level,
1734  "SCardDisconnect } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1735  status);
1736 
1737  return status;
1738 }
1739 
1740 LONG WINAPI Emulate_SCardBeginTransaction(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard)
1741 {
1742  LONG status = scard_handle_valid(smartcard, hCard);
1743 
1744  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardBeginTransaction { hCard: %p",
1745  (void*)hCard);
1746 
1747  if (status == SCARD_S_SUCCESS)
1748  {
1749  SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1750  WINPR_ASSERT(hdl);
1751  if (hdl->transaction)
1752  status = SCARD_E_INVALID_VALUE;
1753  else
1754  hdl->transaction = TRUE;
1755  }
1756 
1757  WLog_Print(smartcard->log, smartcard->log_default_level,
1758  "SCardBeginTransaction } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1759  status);
1760 
1761  return status;
1762 }
1763 
1764 LONG WINAPI Emulate_SCardEndTransaction(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
1765  DWORD dwDisposition)
1766 {
1767  LONG status = scard_handle_valid(smartcard, hCard);
1768 
1769  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardEndTransaction { hCard: %p",
1770  (void*)hCard);
1771 
1772  WINPR_UNUSED(dwDisposition); /* We just ignore this. All return values are static anyway */
1773 
1774  if (status == SCARD_S_SUCCESS)
1775  {
1776  SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1777  WINPR_ASSERT(hdl);
1778  if (!hdl->transaction)
1779  status = SCARD_E_NOT_TRANSACTED;
1780  else
1781  hdl->transaction = FALSE;
1782  }
1783 
1784  WLog_Print(smartcard->log, smartcard->log_default_level,
1785  "SCardEndTransaction } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1786  status);
1787 
1788  return status;
1789 }
1790 
1791 LONG WINAPI Emulate_SCardCancelTransaction(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard)
1792 {
1793  LONG status = scard_handle_valid(smartcard, hCard);
1794 
1795  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardCancelTransaction { hCard: %p",
1796  (void*)hCard);
1797 
1798  if (status == SCARD_S_SUCCESS)
1799  {
1800  SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1801  WINPR_ASSERT(hdl);
1802  if (!hdl->transaction)
1803  status = SCARD_E_NOT_TRANSACTED;
1804  else
1805  hdl->transaction = FALSE;
1806  }
1807 
1808  WLog_Print(smartcard->log, smartcard->log_default_level,
1809  "SCardCancelTransaction } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1810  status);
1811 
1812  return status;
1813 }
1814 
1815 LONG WINAPI Emulate_SCardState(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
1816  LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr,
1817  LPDWORD pcbAtrLen)
1818 {
1819  LONG status = scard_handle_valid(smartcard, hCard);
1820 
1821  if (!pdwState || !pdwProtocol)
1822  status = SCARD_E_INVALID_PARAMETER;
1823 
1824  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardState { hCard: %p",
1825  (void*)hCard);
1826 
1827  if (status == SCARD_S_SUCCESS)
1828  {
1829  SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1830  WINPR_ASSERT(hdl);
1831 
1832  if (pdwState)
1833  *pdwState = SCARD_SPECIFIC;
1834  if (pdwProtocol)
1835  *pdwProtocol = SCARD_PROTOCOL_T1;
1836 
1837  if (pcbAtrLen)
1838  {
1839  SCardContext* ctx =
1840  HashTable_GetItemValue(smartcard->contexts, (const void*)hdl->hContext);
1841  WINPR_ASSERT(ctx);
1842 
1843  for (size_t x = 0; x < MAX_EMULATED_READERS; x++)
1844  {
1845  const SCARD_READERSTATEA* readerA = &ctx->readerStateA[x];
1846  const SCARD_READERSTATEW* readerW = &ctx->readerStateW[x];
1847  if (hdl->unicode)
1848  {
1849  if (_wcscmp(readerW->szReader, hdl->szReader.pw) == 0)
1850  {
1851  *pcbAtrLen = scard_copy_strings(ctx, pbAtr, *pcbAtrLen, readerW->rgbAtr,
1852  readerW->cbAtr);
1853  }
1854  }
1855  else
1856  {
1857  if (strcmp(readerA->szReader, hdl->szReader.pc) == 0)
1858  {
1859  *pcbAtrLen = scard_copy_strings(ctx, pbAtr, *pcbAtrLen, readerA->rgbAtr,
1860  readerA->cbAtr);
1861  }
1862  }
1863  }
1864  }
1865  }
1866 
1867  WLog_Print(smartcard->log, smartcard->log_default_level,
1868  "SCardState } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
1869 
1870  return status;
1871 }
1872 
1873 LONG WINAPI Emulate_SCardStatusA(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
1874  LPSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
1875  LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1876 {
1877  LONG status = scard_handle_valid(smartcard, hCard);
1878 
1879  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardStatusA { hCard: %p",
1880  (void*)hCard);
1881 
1882  if (status == SCARD_S_SUCCESS)
1883  {
1884  SCardContext* ctx = NULL;
1885  SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1886  WINPR_ASSERT(hdl);
1887 
1888  ctx = HashTable_GetItemValue(smartcard->contexts, (const void*)hdl->hContext);
1889  WINPR_ASSERT(ctx);
1890 
1891  if (pcchReaderLen)
1892  *pcchReaderLen =
1893  scard_copy_strings(ctx, mszReaderNames, *pcchReaderLen, hdl->szReader.pc,
1894  (UINT32)strlen(hdl->szReader.pc) + 2);
1895 
1896  if (pdwState)
1897  *pdwState = SCARD_SPECIFIC;
1898  if (pdwProtocol)
1899  *pdwProtocol = SCARD_PROTOCOL_T1;
1900 
1901  if (pcbAtrLen)
1902  {
1903  for (size_t x = 0; x < MAX_EMULATED_READERS; x++)
1904  {
1905  const SCARD_READERSTATEA* reader = &ctx->readerStateA[x];
1906  if (strcmp(reader->szReader, hdl->szReader.pc) == 0)
1907  {
1908  *pcbAtrLen =
1909  scard_copy_strings(ctx, pbAtr, *pcbAtrLen, reader->rgbAtr, reader->cbAtr);
1910  }
1911  }
1912  }
1913  }
1914 
1915  WLog_Print(smartcard->log, smartcard->log_default_level,
1916  "SCardStatusA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
1917 
1918  return status;
1919 }
1920 
1921 LONG WINAPI Emulate_SCardStatusW(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
1922  LPWSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
1923  LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1924 {
1925  LONG status = scard_handle_valid(smartcard, hCard);
1926 
1927  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardStatusW { hCard: %p",
1928  (void*)hCard);
1929 
1930  if (status == SCARD_S_SUCCESS)
1931  {
1932  SCardContext* ctx = NULL;
1933  SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1934  WINPR_ASSERT(hdl);
1935 
1936  ctx = HashTable_GetItemValue(smartcard->contexts, (const void*)hdl->hContext);
1937  WINPR_ASSERT(ctx);
1938 
1939  if (pcchReaderLen)
1940  *pcchReaderLen =
1941  scard_copy_strings(ctx, mszReaderNames, *pcchReaderLen, hdl->szReader.pw,
1942  (UINT32)(_wcslen(hdl->szReader.pw) + 2) * sizeof(WCHAR)) /
1943  sizeof(WCHAR);
1944 
1945  if (pdwState)
1946  *pdwState = SCARD_SPECIFIC;
1947  if (pdwProtocol)
1948  *pdwProtocol = SCARD_PROTOCOL_T1;
1949 
1950  if (pcbAtrLen)
1951  {
1952  for (size_t x = 0; x < MAX_EMULATED_READERS; x++)
1953  {
1954  const SCARD_READERSTATEW* reader = &ctx->readerStateW[x];
1955  if (_wcscmp(reader->szReader, hdl->szReader.pw) == 0)
1956  *pcbAtrLen =
1957  scard_copy_strings(ctx, pbAtr, *pcbAtrLen, reader->rgbAtr, reader->cbAtr);
1958  }
1959  }
1960  }
1961 
1962  WLog_Print(smartcard->log, smartcard->log_default_level,
1963  "SCardStatusW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
1964 
1965  return status;
1966 }
1967 
1968 LONG WINAPI Emulate_SCardTransmit(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
1969  LPCSCARD_IO_REQUEST pioSendPci, LPCBYTE pbSendBuffer,
1970  DWORD cbSendLength, LPSCARD_IO_REQUEST pioRecvPci,
1971  LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
1972 {
1973  LONG status = scard_handle_valid(smartcard, hCard);
1974 
1975  if (!pioSendPci || !pbSendBuffer || !pbRecvBuffer || !pcbRecvLength)
1976  status = SCARD_E_INVALID_PARAMETER;
1977 
1978  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardTransmit { hCard: %p",
1979  (void*)hCard);
1980 
1981  if (status == SCARD_S_SUCCESS)
1982  {
1983  BYTE* response = NULL;
1984  DWORD responseSize = 0;
1985  SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1986  WINPR_ASSERT(hdl);
1987 
1988  hdl->transmitcount++;
1989 
1990  if (!vgids_process_apdu(hdl->vgids, pbSendBuffer, cbSendLength, &response, &responseSize))
1991  status = SCARD_E_NO_SMARTCARD;
1992  else
1993  {
1994  SCardContext* ctx =
1995  HashTable_GetItemValue(smartcard->contexts, (const void*)hdl->hContext);
1996  WINPR_ASSERT(ctx);
1997 
1998  *pcbRecvLength =
1999  scard_copy_strings(ctx, pbRecvBuffer, *pcbRecvLength, response, responseSize);
2000  free(response);
2001 
2002  /* Required */
2003  if (pioRecvPci)
2004  pioRecvPci->dwProtocol = hdl->dwActiveProtocol;
2005  }
2006  }
2007 
2008  WLog_Print(smartcard->log, smartcard->log_default_level,
2009  "SCardTransmit } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
2010 
2011  return status;
2012 }
2013 
2014 LONG WINAPI Emulate_SCardGetTransmitCount(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
2015  LPDWORD pcTransmitCount)
2016 {
2017  LONG status = scard_handle_valid(smartcard, hCard);
2018 
2019  if (!pcTransmitCount)
2020  status = SCARD_E_INVALID_PARAMETER;
2021 
2022  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetTransmitCount { hCard: %p",
2023  (void*)hCard);
2024 
2025  if (status == SCARD_S_SUCCESS)
2026  {
2027  SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
2028  WINPR_ASSERT(hdl);
2029 
2030  *pcTransmitCount = hdl->transmitcount;
2031  }
2032 
2033  WLog_Print(smartcard->log, smartcard->log_default_level,
2034  "SCardGetTransmitCount } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2035  status);
2036 
2037  return status;
2038 }
2039 
2040 LONG WINAPI Emulate_SCardControl(
2041  SmartcardEmulationContext* smartcard, SCARDHANDLE hCard, DWORD dwControlCode,
2042  LPCVOID lpInBuffer, DWORD cbInBufferSize, LPVOID lpOutBuffer, DWORD cbOutBufferSize,
2043  LPDWORD lpBytesReturned /* NOLINT(readability-non-const-parameter) */)
2044 {
2045  LONG status = scard_handle_valid(smartcard, hCard);
2046 
2047  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardControl { hCard: %p",
2048  (void*)hCard);
2049 
2050  if (status == SCARD_S_SUCCESS)
2051  {
2052  WINPR_UNUSED(dwControlCode);
2053  WINPR_UNUSED(lpInBuffer);
2054  WINPR_UNUSED(cbInBufferSize);
2055  WINPR_UNUSED(lpOutBuffer);
2056  WINPR_UNUSED(cbOutBufferSize);
2057  WINPR_UNUSED(lpBytesReturned);
2058 
2059  /* Not required, return not supported */
2060  status = SCARD_E_UNSUPPORTED_FEATURE;
2061  }
2062 
2063  WLog_Print(smartcard->log, smartcard->log_default_level,
2064  "SCardControl } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
2065 
2066  return status;
2067 }
2068 
2069 LONG WINAPI Emulate_SCardGetAttrib(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
2070  DWORD dwAttrId,
2071  LPBYTE pbAttr /* NOLINT(readability-non-const-parameter) */,
2072  LPDWORD pcbAttrLen /* NOLINT(readability-non-const-parameter) */)
2073 {
2074  LONG status = scard_handle_valid(smartcard, hCard);
2075 
2076  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetAttrib { hCard: %p",
2077  (void*)hCard);
2078 
2079  WINPR_UNUSED(dwAttrId);
2080  WINPR_UNUSED(pbAttr);
2081  WINPR_UNUSED(pcbAttrLen);
2082 
2083  /* Not required, return not supported */
2084  if (status == SCARD_S_SUCCESS)
2085  status = SCARD_F_INTERNAL_ERROR;
2086 
2087  WLog_Print(smartcard->log, smartcard->log_default_level,
2088  "SCardGetAttrib } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2089  status);
2090 
2091  return status;
2092 }
2093 
2094 LONG WINAPI Emulate_SCardSetAttrib(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
2095  DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
2096 {
2097  LONG status = scard_handle_valid(smartcard, hCard);
2098 
2099  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardSetAttrib { hCard: %p",
2100  (void*)hCard);
2101 
2102  WINPR_UNUSED(dwAttrId);
2103  WINPR_UNUSED(pbAttr);
2104  WINPR_UNUSED(cbAttrLen);
2105 
2106  /* Not required, return not supported */
2107  if (status == SCARD_S_SUCCESS)
2108  status = SCARD_F_INTERNAL_ERROR;
2109 
2110  WLog_Print(smartcard->log, smartcard->log_default_level,
2111  "SCardSetAttrib } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2112  status);
2113 
2114  return status;
2115 }
2116 
2117 LONG WINAPI Emulate_SCardUIDlgSelectCardA(SmartcardEmulationContext* smartcard,
2118  LPOPENCARDNAMEA_EX pDlgStruc)
2119 {
2120  LONG status = 0;
2121 
2122  WINPR_ASSERT(smartcard);
2123 
2124  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardUIDlgSelectCardA {");
2125 
2126  WINPR_UNUSED(pDlgStruc);
2127 
2128  /* Not required, return not supported */
2129  status = SCARD_E_UNSUPPORTED_FEATURE;
2130 
2131  WLog_Print(smartcard->log, smartcard->log_default_level,
2132  "SCardUIDlgSelectCardA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2133  status);
2134 
2135  return status;
2136 }
2137 
2138 LONG WINAPI Emulate_SCardUIDlgSelectCardW(SmartcardEmulationContext* smartcard,
2139  LPOPENCARDNAMEW_EX pDlgStruc)
2140 {
2141  LONG status = 0;
2142 
2143  WINPR_ASSERT(smartcard);
2144 
2145  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardUIDlgSelectCardW {");
2146 
2147  WINPR_UNUSED(pDlgStruc);
2148 
2149  /* Not required, return not supported */
2150  status = SCARD_E_UNSUPPORTED_FEATURE;
2151 
2152  WLog_Print(smartcard->log, smartcard->log_default_level,
2153  "SCardUIDlgSelectCardW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2154  status);
2155 
2156  return status;
2157 }
2158 
2159 LONG WINAPI Emulate_GetOpenCardNameA(SmartcardEmulationContext* smartcard,
2160  LPOPENCARDNAMEA pDlgStruc)
2161 {
2162  LONG status = 0;
2163 
2164  WINPR_ASSERT(smartcard);
2165 
2166  WLog_Print(smartcard->log, smartcard->log_default_level, "GetOpenCardNameA {");
2167 
2168  WINPR_UNUSED(pDlgStruc);
2169 
2170  /* Not required, return not supported */
2171  status = SCARD_E_UNSUPPORTED_FEATURE;
2172 
2173  WLog_Print(smartcard->log, smartcard->log_default_level,
2174  "GetOpenCardNameA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2175  status);
2176 
2177  return status;
2178 }
2179 
2180 LONG WINAPI Emulate_GetOpenCardNameW(SmartcardEmulationContext* smartcard,
2181  LPOPENCARDNAMEW pDlgStruc)
2182 {
2183  LONG status = 0;
2184 
2185  WINPR_ASSERT(smartcard);
2186 
2187  WLog_Print(smartcard->log, smartcard->log_default_level, "GetOpenCardNameW {");
2188 
2189  WINPR_UNUSED(pDlgStruc);
2190 
2191  /* Not required, return not supported */
2192  status = SCARD_E_UNSUPPORTED_FEATURE;
2193 
2194  WLog_Print(smartcard->log, smartcard->log_default_level,
2195  "GetOpenCardNameW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2196  status);
2197 
2198  return status;
2199 }
2200 
2201 LONG WINAPI Emulate_SCardDlgExtendedError(SmartcardEmulationContext* smartcard)
2202 {
2203  LONG status = 0;
2204 
2205  WINPR_ASSERT(smartcard);
2206 
2207  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardDlgExtendedError {");
2208 
2209  /* Not required, return not supported */
2210  status = SCARD_E_UNSUPPORTED_FEATURE;
2211 
2212  WLog_Print(smartcard->log, smartcard->log_default_level,
2213  "SCardDlgExtendedError } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2214  status);
2215 
2216  return status;
2217 }
2218 
2219 LONG WINAPI Emulate_SCardReadCacheA(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
2220  UUID* CardIdentifier, DWORD FreshnessCounter, LPSTR LookupName,
2221  PBYTE Data, DWORD* DataLen)
2222 {
2223  DWORD count = 0;
2224  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2225 
2226  if (!CardIdentifier || !DataLen)
2227  status = SCARD_E_INVALID_PARAMETER;
2228 
2229  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardReadCacheA { hContext: %p",
2230  (void*)hContext);
2231 
2232  if (DataLen)
2233  {
2234  count = *DataLen;
2235  *DataLen = 0;
2236  }
2237 
2238  if (status == SCARD_S_SUCCESS)
2239  {
2240  SCardCacheItem* data = NULL;
2241  SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
2242  WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
2243 
2244  char* id = card_id_and_name_a(CardIdentifier, LookupName);
2245  data = HashTable_GetItemValue(value->cache, id);
2246  free(id);
2247 
2248  if (!data)
2249  status = SCARD_W_CACHE_ITEM_NOT_FOUND;
2250  else if (data->freshness != FreshnessCounter)
2251  status = SCARD_W_CACHE_ITEM_STALE;
2252  else
2253  *DataLen = scard_copy_strings(value, Data, count, data->data, data->size);
2254  }
2255 
2256  WLog_Print(smartcard->log, smartcard->log_default_level,
2257  "SCardReadCacheA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2258  status);
2259 
2260  return status;
2261 }
2262 
2263 LONG WINAPI Emulate_SCardReadCacheW(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
2264  UUID* CardIdentifier, DWORD FreshnessCounter, LPWSTR LookupName,
2265  PBYTE Data, DWORD* DataLen)
2266 {
2267  DWORD count = 0;
2268  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2269 
2270  if (!CardIdentifier || !DataLen)
2271  status = SCARD_E_INVALID_PARAMETER;
2272 
2273  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardReadCacheW { hContext: %p",
2274  (void*)hContext);
2275 
2276  if (DataLen)
2277  {
2278  count = *DataLen;
2279  *DataLen = 0;
2280  }
2281 
2282  if (status == SCARD_S_SUCCESS)
2283  {
2284  SCardCacheItem* data = NULL;
2285  SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
2286  WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
2287 
2288  char* id = card_id_and_name_w(CardIdentifier, LookupName);
2289  data = HashTable_GetItemValue(value->cache, id);
2290  free(id);
2291  if (!data)
2292  status = SCARD_W_CACHE_ITEM_NOT_FOUND;
2293  else if (data->freshness != FreshnessCounter)
2294  status = SCARD_W_CACHE_ITEM_STALE;
2295  else
2296  *DataLen = scard_copy_strings(value, Data, count, data->data, data->size);
2297  }
2298 
2299  WLog_Print(smartcard->log, smartcard->log_default_level,
2300  "SCardReadCacheW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2301  status);
2302 
2303  return status;
2304 }
2305 
2306 static LONG insert_data(wHashTable* table, DWORD FreshnessCounter, const char* key,
2307  const PBYTE Data, DWORD DataLen)
2308 {
2309  BOOL rc = 0;
2310  SCardCacheItem* item = NULL;
2311 
2312  WINPR_ASSERT(table);
2313  WINPR_ASSERT(key);
2314 
2315  if (DataLen > MAX_CACHE_ITEM_SIZE)
2316  return SCARD_W_CACHE_ITEM_TOO_BIG;
2317 
2318  if (HashTable_Count(table) > MAX_CACHE_ITEM_VALUES)
2319  return SCARD_E_WRITE_TOO_MANY;
2320 
2321  item = HashTable_GetItemValue(table, key);
2322  if (!item)
2323  {
2324  item = calloc(1, sizeof(SCardCacheItem));
2325  if (!item)
2326  return SCARD_E_NO_MEMORY;
2327 
2328  rc = HashTable_Insert(table, key, item);
2329  if (!rc)
2330  {
2331  free(item);
2332  return SCARD_E_NO_MEMORY;
2333  }
2334  }
2335 
2336  if (item->freshness > FreshnessCounter)
2337  return SCARD_W_CACHE_ITEM_STALE;
2338  item->freshness = FreshnessCounter;
2339  item->size = DataLen;
2340  memcpy(item->data, Data, DataLen);
2341 
2342  // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): HashTable_Insert takes ownership of item
2343  return SCARD_S_SUCCESS;
2344 }
2345 
2346 LONG WINAPI Emulate_SCardWriteCacheA(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
2347  UUID* CardIdentifier, DWORD FreshnessCounter, LPSTR LookupName,
2348  PBYTE Data, DWORD DataLen)
2349 {
2350  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2351 
2352  if (!CardIdentifier)
2353  status = SCARD_E_INVALID_PARAMETER;
2354 
2355  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardWriteCacheA { hContext: %p",
2356  (void*)hContext);
2357 
2358  if (status == SCARD_S_SUCCESS)
2359  {
2360  SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
2361  WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
2362 
2363  char* id = card_id_and_name_a(CardIdentifier, LookupName);
2364  if (!id)
2365  status = SCARD_E_NO_MEMORY;
2366  else
2367  {
2368  status = insert_data(value->cache, FreshnessCounter, id, Data, DataLen);
2369  free(id);
2370  }
2371  }
2372 
2373  WLog_Print(smartcard->log, smartcard->log_default_level,
2374  "SCardWriteCacheA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2375  status);
2376 
2377  return status;
2378 }
2379 
2380 LONG WINAPI Emulate_SCardWriteCacheW(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
2381  UUID* CardIdentifier, DWORD FreshnessCounter,
2382  LPWSTR LookupName, PBYTE Data, DWORD DataLen)
2383 {
2384  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2385 
2386  if (!CardIdentifier)
2387  status = SCARD_E_INVALID_PARAMETER;
2388 
2389  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardWriteCacheW { hContext: %p",
2390  (void*)hContext);
2391 
2392  if (status == SCARD_S_SUCCESS)
2393  {
2394  SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
2395  WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
2396 
2397  char* id = card_id_and_name_w(CardIdentifier, LookupName);
2398  if (!id)
2399  status = SCARD_E_NO_MEMORY;
2400  else
2401  {
2402  status = insert_data(value->cache, FreshnessCounter, id, Data, DataLen);
2403  free(id);
2404  }
2405  }
2406 
2407  WLog_Print(smartcard->log, smartcard->log_default_level,
2408  "SCardWriteCacheW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2409  status);
2410 
2411  return status;
2412 }
2413 
2414 LONG WINAPI Emulate_SCardGetReaderIconA(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
2415  LPCSTR szReaderName, LPBYTE pbIcon, LPDWORD pcbIcon)
2416 {
2417  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2418 
2419  if (!szReaderName || !pcbIcon)
2420  status = SCARD_E_INVALID_PARAMETER;
2421 
2422  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetReaderIconA { hContext: %p",
2423  (void*)hContext);
2424 
2425  if (status == SCARD_S_SUCCESS)
2426  status = scard_reader_name_valid_a(smartcard, hContext, szReaderName);
2427 
2428  if (status == SCARD_S_SUCCESS)
2429  {
2430  SCardContext* ctx = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
2431  WINPR_ASSERT(ctx);
2432 
2433  if (pbIcon)
2434  *pcbIcon = scard_copy_strings(ctx, pbIcon, *pcbIcon, resources_FreeRDP_ico,
2435  resources_FreeRDP_ico_len);
2436  else
2437  *pcbIcon = resources_FreeRDP_ico_len;
2438  }
2439 
2440  WLog_Print(smartcard->log, smartcard->log_default_level,
2441  "SCardGetReaderIconA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2442  status);
2443 
2444  return status;
2445 }
2446 
2447 LONG WINAPI Emulate_SCardGetReaderIconW(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
2448  LPCWSTR szReaderName, LPBYTE pbIcon, LPDWORD pcbIcon)
2449 {
2450  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2451 
2452  if (!szReaderName || !pcbIcon)
2453  status = SCARD_E_INVALID_PARAMETER;
2454 
2455  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetReaderIconW { hContext: %p",
2456  (void*)hContext);
2457 
2458  if (status == SCARD_S_SUCCESS)
2459  status = scard_reader_name_valid_w(smartcard, hContext, szReaderName);
2460 
2461  if (status == SCARD_S_SUCCESS)
2462  {
2463  SCardContext* ctx = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
2464  WINPR_ASSERT(ctx);
2465 
2466  if (pbIcon)
2467  *pcbIcon = scard_copy_strings(ctx, pbIcon, *pcbIcon, resources_FreeRDP_ico,
2468  resources_FreeRDP_ico_len);
2469  else
2470  *pcbIcon = resources_FreeRDP_ico_len;
2471  }
2472 
2473  WLog_Print(smartcard->log, smartcard->log_default_level,
2474  "SCardGetReaderIconW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2475  status);
2476 
2477  return status;
2478 }
2479 
2480 LONG WINAPI Emulate_SCardGetDeviceTypeIdA(SmartcardEmulationContext* smartcard,
2481  SCARDCONTEXT hContext, LPCSTR szReaderName,
2482  LPDWORD pdwDeviceTypeId)
2483 {
2484  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2485 
2486  if (!pdwDeviceTypeId)
2487  status = SCARD_E_INVALID_PARAMETER;
2488 
2489  if (status == SCARD_S_SUCCESS)
2490  status = scard_reader_name_valid_a(smartcard, hContext, szReaderName);
2491 
2492  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetDeviceTypeIdA { hContext: %p",
2493  (void*)hContext);
2494 
2495  if (status == SCARD_S_SUCCESS)
2496  {
2497  *pdwDeviceTypeId = SCARD_READER_TYPE_USB; // SCARD_READER_TYPE_TPM
2498  }
2499 
2500  WLog_Print(smartcard->log, smartcard->log_default_level,
2501  "SCardGetDeviceTypeIdA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2502  status);
2503 
2504  return status;
2505 }
2506 
2507 LONG WINAPI Emulate_SCardGetDeviceTypeIdW(SmartcardEmulationContext* smartcard,
2508  SCARDCONTEXT hContext, LPCWSTR szReaderName,
2509  LPDWORD pdwDeviceTypeId)
2510 {
2511  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2512 
2513  if (!pdwDeviceTypeId)
2514  status = SCARD_E_INVALID_PARAMETER;
2515 
2516  if (status == SCARD_S_SUCCESS)
2517  status = scard_reader_name_valid_w(smartcard, hContext, szReaderName);
2518 
2519  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetDeviceTypeIdW { hContext: %p",
2520  (void*)hContext);
2521 
2522  if (status == SCARD_S_SUCCESS)
2523  {
2524  *pdwDeviceTypeId = SCARD_READER_TYPE_USB; // SCARD_READER_TYPE_TPM
2525  }
2526 
2527  WLog_Print(smartcard->log, smartcard->log_default_level,
2528  "SCardGetDeviceTypeIdW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2529  status);
2530 
2531  return status;
2532 }
2533 
2534 LONG WINAPI Emulate_SCardGetReaderDeviceInstanceIdA(
2535  SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext, LPCSTR szReaderName,
2536  LPSTR szDeviceInstanceId /* NOLINT(readability-non-const-parameter) */,
2537  LPDWORD pcchDeviceInstanceId /* NOLINT(readability-non-const-parameter) */)
2538 {
2539  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2540 
2541  if (status == SCARD_S_SUCCESS)
2542  status = scard_reader_name_valid_a(smartcard, hContext, szReaderName);
2543 
2544  WLog_Print(smartcard->log, smartcard->log_default_level,
2545  "SCardGetReaderDeviceInstanceIdA { hContext: %p", (void*)hContext);
2546 
2547  WINPR_UNUSED(szDeviceInstanceId);
2548  WINPR_UNUSED(pcchDeviceInstanceId);
2549 
2550  /* Not required, return not supported */
2551  if (status == SCARD_S_SUCCESS)
2552  status = SCARD_E_UNSUPPORTED_FEATURE;
2553 
2554  WLog_Print(smartcard->log, smartcard->log_default_level,
2555  "SCardGetReaderDeviceInstanceIdA } status: %s (0x%08" PRIX32 ")",
2556  SCardGetErrorString(status), status);
2557 
2558  return status;
2559 }
2560 
2561 LONG WINAPI Emulate_SCardGetReaderDeviceInstanceIdW(
2562  SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext, LPCWSTR szReaderName,
2563  LPWSTR szDeviceInstanceId /* NOLINT(readability-non-const-parameter) */,
2564  LPDWORD pcchDeviceInstanceId /* NOLINT(readability-non-const-parameter) */)
2565 {
2566  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2567 
2568  if (status == SCARD_S_SUCCESS)
2569  status = scard_reader_name_valid_w(smartcard, hContext, szReaderName);
2570 
2571  WLog_Print(smartcard->log, smartcard->log_default_level,
2572  "SCardGetReaderDeviceInstanceIdW { hContext: %p", (void*)hContext);
2573 
2574  WINPR_UNUSED(szDeviceInstanceId);
2575  WINPR_UNUSED(pcchDeviceInstanceId);
2576 
2577  /* Not required, return not supported */
2578  if (status == SCARD_S_SUCCESS)
2579  status = SCARD_E_UNSUPPORTED_FEATURE;
2580 
2581  WLog_Print(smartcard->log, smartcard->log_default_level,
2582  "SCardGetReaderDeviceInstanceIdW } status: %s (0x%08" PRIX32 ")",
2583  SCardGetErrorString(status), status);
2584 
2585  return status;
2586 }
2587 
2588 LONG WINAPI Emulate_SCardListReadersWithDeviceInstanceIdA(
2589  SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext, LPCSTR szDeviceInstanceId,
2590  LPSTR mszReaders /* NOLINT(readability-non-const-parameter) */,
2591  LPDWORD pcchReaders /* NOLINT(readability-non-const-parameter) */)
2592 {
2593  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2594 
2595  WLog_Print(smartcard->log, smartcard->log_default_level,
2596  "SCardListReadersWithDeviceInstanceIdA { hContext: %p", (void*)hContext);
2597 
2598  WINPR_UNUSED(szDeviceInstanceId);
2599  WINPR_UNUSED(mszReaders);
2600  WINPR_UNUSED(pcchReaders);
2601 
2602  /* Not required, return not supported */
2603  if (status == SCARD_S_SUCCESS)
2604  status = SCARD_E_UNSUPPORTED_FEATURE;
2605 
2606  WLog_Print(smartcard->log, smartcard->log_default_level,
2607  "SCardListReadersWithDeviceInstanceIdA } status: %s (0x%08" PRIX32 ")",
2608  SCardGetErrorString(status), status);
2609 
2610  return status;
2611 }
2612 
2613 LONG WINAPI Emulate_SCardListReadersWithDeviceInstanceIdW(
2614  SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext, LPCWSTR szDeviceInstanceId,
2615  LPWSTR mszReaders /* NOLINT(readability-non-const-parameter) */, LPDWORD pcchReaders)
2616 {
2617  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2618 
2619  WLog_Print(smartcard->log, smartcard->log_default_level,
2620  "SCardListReadersWithDeviceInstanceIdW { hContext: %p", (void*)hContext);
2621 
2622  WINPR_UNUSED(szDeviceInstanceId);
2623  WINPR_UNUSED(mszReaders);
2624  WINPR_UNUSED(pcchReaders);
2625 
2626  /* Not required, return not supported */
2627  if (status == SCARD_S_SUCCESS)
2628  status = SCARD_E_UNSUPPORTED_FEATURE;
2629 
2630  WLog_Print(smartcard->log, smartcard->log_default_level,
2631  "SCardListReadersWithDeviceInstanceIdW } status: %s (0x%08" PRIX32 ")",
2632  SCardGetErrorString(status), status);
2633 
2634  return status;
2635 }
2636 
2637 LONG WINAPI Emulate_SCardAudit(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
2638  DWORD dwEvent)
2639 {
2640  LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2641 
2642  WINPR_UNUSED(dwEvent);
2643 
2644  WLog_Print(smartcard->log, smartcard->log_default_level, "SCardAudit { hContext: %p",
2645  (void*)hContext);
2646 
2647  // TODO: Implement
2648  if (status == SCARD_S_SUCCESS)
2649  status = SCARD_E_UNSUPPORTED_FEATURE;
2650 
2651  WLog_Print(smartcard->log, smartcard->log_default_level,
2652  "SCardAudit } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
2653 
2654  return status;
2655 }
2656 
2657 static BOOL context_equals(const void* pva, const void* pvb)
2658 {
2659  const SCARDCONTEXT a = (const SCARDCONTEXT)pva;
2660  const SCARDCONTEXT b = (const SCARDCONTEXT)pvb;
2661  if (!a && !b)
2662  return TRUE;
2663  if (!a || !b)
2664  return FALSE;
2665 
2666  return a == b;
2667 }
2668 
2669 static BOOL handle_equals(const void* pva, const void* pvb)
2670 {
2671  const SCARDHANDLE a = (const SCARDHANDLE)pva;
2672  const SCARDHANDLE b = (const SCARDHANDLE)pvb;
2673  if (!a && !b)
2674  return TRUE;
2675  if (!a || !b)
2676  return FALSE;
2677 
2678  return a == b;
2679 }
2680 
2681 SmartcardEmulationContext* Emulate_New(const rdpSettings* settings)
2682 {
2683  SmartcardEmulationContext* smartcard = NULL;
2684 
2685  WINPR_ASSERT(settings);
2686 
2687  smartcard = calloc(1, sizeof(SmartcardEmulationContext));
2688  if (!smartcard)
2689  goto fail;
2690 
2691  smartcard->settings = settings;
2692  smartcard->log = WLog_Get("EmulateSCard");
2693  if (!smartcard->log)
2694  goto fail;
2695  smartcard->log_default_level = WLOG_TRACE;
2696 
2697  smartcard->contexts = HashTable_New(FALSE);
2698  if (!smartcard->contexts)
2699  goto fail;
2700  else
2701  {
2702  wObject* obj = HashTable_KeyObject(smartcard->contexts);
2703  WINPR_ASSERT(obj);
2704  obj->fnObjectEquals = context_equals;
2705  }
2706  if (!smartcard->contexts)
2707  goto fail;
2708  else
2709  {
2710  wObject* obj = HashTable_ValueObject(smartcard->contexts);
2711  WINPR_ASSERT(obj);
2712  obj->fnObjectFree = scard_context_free;
2713  }
2714 
2715  smartcard->handles = HashTable_New(FALSE);
2716  if (!smartcard->handles)
2717  goto fail;
2718  else
2719  {
2720  wObject* obj = HashTable_KeyObject(smartcard->handles);
2721  WINPR_ASSERT(obj);
2722  obj->fnObjectEquals = handle_equals;
2723  }
2724  if (!smartcard->handles)
2725  goto fail;
2726  else
2727  {
2728  wObject* obj = HashTable_ValueObject(smartcard->handles);
2729  WINPR_ASSERT(obj);
2730  obj->fnObjectFree = scard_handle_free;
2731  }
2732 
2733  return smartcard;
2734 
2735 fail:
2736  WINPR_PRAGMA_DIAG_PUSH
2737  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2738  Emulate_Free(smartcard);
2739  WINPR_PRAGMA_DIAG_POP
2740  return NULL;
2741 }
2742 
2743 void Emulate_Free(SmartcardEmulationContext* context)
2744 {
2745  if (!context)
2746  return;
2747 
2748  HashTable_Free(context->handles);
2749  HashTable_Free(context->contexts);
2750  free(context);
2751 }
2752 
2753 BOOL Emulate_IsConfigured(SmartcardEmulationContext* context)
2754 {
2755  BOOL rc = FALSE;
2756  vgidsContext* vgids = NULL;
2757  const char* pem = NULL;
2758  const char* key = NULL;
2759  const char* pin = NULL;
2760 
2761  WINPR_ASSERT(context);
2762 
2763  pem = freerdp_settings_get_string(context->settings, FreeRDP_SmartcardCertificate);
2764  key = freerdp_settings_get_string(context->settings, FreeRDP_SmartcardPrivateKey);
2765  pin = freerdp_settings_get_string(context->settings, FreeRDP_Password);
2766 
2767  /* Cache result only, if no initialization arguments changed. */
2768  if ((context->pem == pem) && (context->key == key) && (context->pin == pin))
2769  return context->configured;
2770 
2771  context->pem = pem;
2772  context->key = key;
2773  context->pin = pin;
2774 
2775  vgids = vgids_new();
2776  if (vgids)
2777  rc = vgids_init(vgids, context->pem, context->key, context->pin);
2778  vgids_free(vgids);
2779 
2780  context->configured = rc;
2781  return rc;
2782 }
FREERDP_API const void * freerdp_settings_get_pointer(const rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a immutable pointer 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.
Definition: collections.h:57