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