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