FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
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 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 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 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 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 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 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 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 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 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 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 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 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 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), 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), 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), 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), 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), 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), 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 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 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 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 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 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 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), 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), 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), 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), 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), 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), 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 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 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 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 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 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 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 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 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 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), status);
1554
1555 return status;
1556}
1557
1558SCardHandle* find_reader(SmartcardEmulationContext* smartcard, const void* szReader, BOOL unicode)
1559{
1560 SCardHandle* hdl = NULL;
1561 UINT_PTR* keys = NULL;
1562 size_t count = 0;
1563
1564 WINPR_ASSERT(smartcard);
1565 count = HashTable_GetKeys(smartcard->handles, &keys);
1566 for (size_t x = 0; x < count; x++)
1567 {
1568 SCardHandle* cur = HashTable_GetItemValue(smartcard->handles, (const void*)keys[x]);
1569 WINPR_ASSERT(cur);
1570
1571 if (cur->unicode != unicode)
1572 continue;
1573 if (!unicode && (strcmp(cur->szReader.pc, szReader) != 0))
1574 continue;
1575 if (unicode && (_wcscmp(cur->szReader.pw, szReader) != 0))
1576 continue;
1577 hdl = cur;
1578 break;
1579 }
1580 free(keys);
1581 return hdl;
1582}
1583
1584static SCardHandle* reader2handle(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
1585 const void* szReader, BOOL unicode, DWORD dwShareMode,
1586 SCARDHANDLE* phCard, DWORD dwPreferredProtocols,
1587 LPDWORD pdwActiveProtocol)
1588{
1589 SCardHandle* hdl = NULL;
1590
1591 WINPR_ASSERT(phCard);
1592
1593 *phCard = 0;
1594 if (Emulate_SCardIsValidContext(smartcard, hContext) != SCARD_S_SUCCESS)
1595 return NULL;
1596
1597 hdl = scard_handle_new(smartcard, hContext, szReader, unicode);
1598 if (hdl)
1599 {
1600 winpr_RAND(&hdl->card, sizeof(hdl->card));
1601 hdl->dwActiveProtocol = SCARD_PROTOCOL_T1;
1602 hdl->dwShareMode = dwShareMode;
1603
1604 if (!HashTable_Insert(smartcard->handles, (const void*)hdl->card, hdl))
1605 {
1606 scard_handle_free(hdl);
1607 hdl = NULL;
1608 }
1609 else
1610 {
1611 if (pdwActiveProtocol)
1612 {
1613 if ((hdl->dwActiveProtocol & dwPreferredProtocols) == 0)
1614 {
1615 scard_handle_free(hdl);
1616 hdl = NULL;
1617 }
1618 else
1619 *pdwActiveProtocol = hdl->dwActiveProtocol;
1620 }
1621 if (hdl)
1622 {
1623 hdl->referencecount++;
1624 *phCard = hdl->card;
1625 }
1626 }
1627 }
1628 WLog_Print(smartcard->log, smartcard->log_default_level, "{ %p }", (void*)*phCard);
1629 return hdl;
1630}
1631
1632LONG WINAPI Emulate_SCardConnectA(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
1633 LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
1634 LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
1635{
1636 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1637
1638 if (!phCard || !pdwActiveProtocol)
1639 status = SCARD_E_INVALID_PARAMETER;
1640
1641 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardConnectA { hContext: %p",
1642 (void*)hContext);
1643
1644 if (status == SCARD_S_SUCCESS)
1645 {
1646 if (!reader2handle(smartcard, hContext, szReader, FALSE, dwShareMode, phCard,
1647 dwPreferredProtocols, pdwActiveProtocol))
1648 status = SCARD_E_NO_MEMORY;
1649 }
1650
1651 WLog_Print(smartcard->log, smartcard->log_default_level,
1652 "SCardConnectA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
1653
1654 return status;
1655}
1656
1657LONG WINAPI Emulate_SCardConnectW(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
1658 LPCWSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
1659 LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
1660{
1661 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
1662
1663 if (!phCard || !pdwActiveProtocol)
1664 status = SCARD_E_INVALID_PARAMETER;
1665
1666 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardConnectW { hContext: %p",
1667 (void*)hContext);
1668
1669 if (status == SCARD_S_SUCCESS)
1670 {
1671 if (!reader2handle(smartcard, hContext, szReader, TRUE, dwShareMode, phCard,
1672 dwPreferredProtocols, pdwActiveProtocol))
1673 status = SCARD_E_NO_MEMORY;
1674 }
1675
1676 WLog_Print(smartcard->log, smartcard->log_default_level,
1677 "SCardConnectW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
1678
1679 return status;
1680}
1681
1682LONG WINAPI Emulate_SCardReconnect(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
1683 DWORD dwShareMode, WINPR_ATTR_UNUSED DWORD dwPreferredProtocols,
1684 WINPR_ATTR_UNUSED DWORD dwInitialization,
1685 LPDWORD pdwActiveProtocol)
1686{
1687 LONG status = scard_handle_valid(smartcard, hCard);
1688
1689 if (!pdwActiveProtocol)
1690 status = SCARD_E_INVALID_PARAMETER;
1691
1692 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardReconnect { hCard: %p",
1693 (void*)hCard);
1694
1695 if (status == SCARD_S_SUCCESS)
1696 {
1697 SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1698 WINPR_ASSERT(hdl);
1699
1700 // TODO: Implement
1701 hdl->dwShareMode = dwShareMode;
1702 hdl->transaction = FALSE;
1703
1704 *pdwActiveProtocol = hdl->dwActiveProtocol;
1705 }
1706
1707 WLog_Print(smartcard->log, smartcard->log_default_level,
1708 "SCardReconnect } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1709 status);
1710
1711 return status;
1712}
1713
1714LONG WINAPI Emulate_SCardDisconnect(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
1715 DWORD dwDisposition)
1716{
1717 LONG status = scard_handle_valid(smartcard, hCard);
1718
1719 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardDisconnect { hCard: %p",
1720 (void*)hCard);
1721
1722 WINPR_UNUSED(dwDisposition); /* We just ignore this. All return values are static anyway */
1723
1724 if (status == SCARD_S_SUCCESS)
1725 {
1726 SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1727 WINPR_ASSERT(hdl);
1728
1729 hdl->referencecount--;
1730 if (hdl->referencecount == 0)
1731 HashTable_Remove(smartcard->handles, (const void*)hCard);
1732 }
1733
1734 WLog_Print(smartcard->log, smartcard->log_default_level,
1735 "SCardDisconnect } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1736 status);
1737
1738 return status;
1739}
1740
1741LONG WINAPI Emulate_SCardBeginTransaction(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard)
1742{
1743 LONG status = scard_handle_valid(smartcard, hCard);
1744
1745 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardBeginTransaction { hCard: %p",
1746 (void*)hCard);
1747
1748 if (status == SCARD_S_SUCCESS)
1749 {
1750 SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1751 WINPR_ASSERT(hdl);
1752 if (hdl->transaction)
1753 status = SCARD_E_INVALID_VALUE;
1754 else
1755 hdl->transaction = TRUE;
1756 }
1757
1758 WLog_Print(smartcard->log, smartcard->log_default_level,
1759 "SCardBeginTransaction } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1760 status);
1761
1762 return status;
1763}
1764
1765LONG WINAPI Emulate_SCardEndTransaction(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
1766 DWORD dwDisposition)
1767{
1768 LONG status = scard_handle_valid(smartcard, hCard);
1769
1770 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardEndTransaction { hCard: %p",
1771 (void*)hCard);
1772
1773 WINPR_UNUSED(dwDisposition); /* We just ignore this. All return values are static anyway */
1774
1775 if (status == SCARD_S_SUCCESS)
1776 {
1777 SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1778 WINPR_ASSERT(hdl);
1779 if (!hdl->transaction)
1780 status = SCARD_E_NOT_TRANSACTED;
1781 else
1782 hdl->transaction = FALSE;
1783 }
1784
1785 WLog_Print(smartcard->log, smartcard->log_default_level,
1786 "SCardEndTransaction } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1787 status);
1788
1789 return status;
1790}
1791
1792LONG WINAPI Emulate_SCardCancelTransaction(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard)
1793{
1794 LONG status = scard_handle_valid(smartcard, hCard);
1795
1796 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardCancelTransaction { hCard: %p",
1797 (void*)hCard);
1798
1799 if (status == SCARD_S_SUCCESS)
1800 {
1801 SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1802 WINPR_ASSERT(hdl);
1803 if (!hdl->transaction)
1804 status = SCARD_E_NOT_TRANSACTED;
1805 else
1806 hdl->transaction = FALSE;
1807 }
1808
1809 WLog_Print(smartcard->log, smartcard->log_default_level,
1810 "SCardCancelTransaction } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
1811 status);
1812
1813 return status;
1814}
1815
1816LONG WINAPI Emulate_SCardState(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
1817 LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr,
1818 LPDWORD pcbAtrLen)
1819{
1820 LONG status = scard_handle_valid(smartcard, hCard);
1821
1822 if (!pdwState || !pdwProtocol)
1823 status = SCARD_E_INVALID_PARAMETER;
1824
1825 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardState { hCard: %p",
1826 (void*)hCard);
1827
1828 if (status == SCARD_S_SUCCESS)
1829 {
1830 SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1831 WINPR_ASSERT(hdl);
1832
1833 if (pdwState)
1834 *pdwState = SCARD_SPECIFIC;
1835 if (pdwProtocol)
1836 *pdwProtocol = SCARD_PROTOCOL_T1;
1837
1838 if (pcbAtrLen)
1839 {
1840 SCardContext* ctx =
1841 HashTable_GetItemValue(smartcard->contexts, (const void*)hdl->hContext);
1842 WINPR_ASSERT(ctx);
1843
1844 for (size_t x = 0; x < MAX_EMULATED_READERS; x++)
1845 {
1846 const SCARD_READERSTATEA* readerA = &ctx->readerStateA[x];
1847 const SCARD_READERSTATEW* readerW = &ctx->readerStateW[x];
1848 if (hdl->unicode)
1849 {
1850 if (_wcscmp(readerW->szReader, hdl->szReader.pw) == 0)
1851 {
1852 *pcbAtrLen = scard_copy_strings(ctx, pbAtr, *pcbAtrLen, readerW->rgbAtr,
1853 readerW->cbAtr);
1854 }
1855 }
1856 else
1857 {
1858 if (strcmp(readerA->szReader, hdl->szReader.pc) == 0)
1859 {
1860 *pcbAtrLen = scard_copy_strings(ctx, pbAtr, *pcbAtrLen, readerA->rgbAtr,
1861 readerA->cbAtr);
1862 }
1863 }
1864 }
1865 }
1866 }
1867
1868 WLog_Print(smartcard->log, smartcard->log_default_level,
1869 "SCardState } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
1870
1871 return status;
1872}
1873
1874LONG WINAPI Emulate_SCardStatusA(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
1875 LPSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
1876 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1877{
1878 LONG status = scard_handle_valid(smartcard, hCard);
1879
1880 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardStatusA { hCard: %p",
1881 (void*)hCard);
1882
1883 if (status == SCARD_S_SUCCESS)
1884 {
1885 SCardContext* ctx = NULL;
1886 SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1887 WINPR_ASSERT(hdl);
1888
1889 ctx = HashTable_GetItemValue(smartcard->contexts, (const void*)hdl->hContext);
1890 WINPR_ASSERT(ctx);
1891
1892 if (pcchReaderLen)
1893 *pcchReaderLen =
1894 scard_copy_strings(ctx, mszReaderNames, *pcchReaderLen, hdl->szReader.pc,
1895 (UINT32)strlen(hdl->szReader.pc) + 2);
1896
1897 if (pdwState)
1898 *pdwState = SCARD_SPECIFIC;
1899 if (pdwProtocol)
1900 *pdwProtocol = SCARD_PROTOCOL_T1;
1901
1902 if (pcbAtrLen)
1903 {
1904 for (size_t x = 0; x < MAX_EMULATED_READERS; x++)
1905 {
1906 const SCARD_READERSTATEA* reader = &ctx->readerStateA[x];
1907 if (strcmp(reader->szReader, hdl->szReader.pc) == 0)
1908 {
1909 *pcbAtrLen =
1910 scard_copy_strings(ctx, pbAtr, *pcbAtrLen, reader->rgbAtr, reader->cbAtr);
1911 }
1912 }
1913 }
1914 }
1915
1916 WLog_Print(smartcard->log, smartcard->log_default_level,
1917 "SCardStatusA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
1918
1919 return status;
1920}
1921
1922LONG WINAPI Emulate_SCardStatusW(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
1923 LPWSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
1924 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1925{
1926 LONG status = scard_handle_valid(smartcard, hCard);
1927
1928 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardStatusW { hCard: %p",
1929 (void*)hCard);
1930
1931 if (status == SCARD_S_SUCCESS)
1932 {
1933 SCardContext* ctx = NULL;
1934 SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1935 WINPR_ASSERT(hdl);
1936
1937 ctx = HashTable_GetItemValue(smartcard->contexts, (const void*)hdl->hContext);
1938 WINPR_ASSERT(ctx);
1939
1940 if (pcchReaderLen)
1941 *pcchReaderLen =
1942 scard_copy_strings(ctx, mszReaderNames, *pcchReaderLen, hdl->szReader.pw,
1943 (UINT32)(_wcslen(hdl->szReader.pw) + 2) * sizeof(WCHAR)) /
1944 sizeof(WCHAR);
1945
1946 if (pdwState)
1947 *pdwState = SCARD_SPECIFIC;
1948 if (pdwProtocol)
1949 *pdwProtocol = SCARD_PROTOCOL_T1;
1950
1951 if (pcbAtrLen)
1952 {
1953 for (size_t x = 0; x < MAX_EMULATED_READERS; x++)
1954 {
1955 const SCARD_READERSTATEW* reader = &ctx->readerStateW[x];
1956 if (_wcscmp(reader->szReader, hdl->szReader.pw) == 0)
1957 *pcbAtrLen =
1958 scard_copy_strings(ctx, pbAtr, *pcbAtrLen, reader->rgbAtr, reader->cbAtr);
1959 }
1960 }
1961 }
1962
1963 WLog_Print(smartcard->log, smartcard->log_default_level,
1964 "SCardStatusW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
1965
1966 return status;
1967}
1968
1969LONG WINAPI Emulate_SCardTransmit(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
1970 LPCSCARD_IO_REQUEST pioSendPci, LPCBYTE pbSendBuffer,
1971 DWORD cbSendLength, LPSCARD_IO_REQUEST pioRecvPci,
1972 LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
1973{
1974 LONG status = scard_handle_valid(smartcard, hCard);
1975
1976 if (!pioSendPci || !pbSendBuffer || !pbRecvBuffer || !pcbRecvLength)
1977 status = SCARD_E_INVALID_PARAMETER;
1978
1979 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardTransmit { hCard: %p",
1980 (void*)hCard);
1981
1982 if (status == SCARD_S_SUCCESS)
1983 {
1984 BYTE* response = NULL;
1985 DWORD responseSize = 0;
1986 SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
1987 WINPR_ASSERT(hdl);
1988
1989 hdl->transmitcount++;
1990
1991 if (!vgids_process_apdu(hdl->vgids, pbSendBuffer, cbSendLength, &response, &responseSize))
1992 status = SCARD_E_NO_SMARTCARD;
1993 else
1994 {
1995 SCardContext* ctx =
1996 HashTable_GetItemValue(smartcard->contexts, (const void*)hdl->hContext);
1997 WINPR_ASSERT(ctx);
1998
1999 *pcbRecvLength =
2000 scard_copy_strings(ctx, pbRecvBuffer, *pcbRecvLength, response, responseSize);
2001 free(response);
2002
2003 /* Required */
2004 if (pioRecvPci)
2005 pioRecvPci->dwProtocol = hdl->dwActiveProtocol;
2006 }
2007 }
2008
2009 WLog_Print(smartcard->log, smartcard->log_default_level,
2010 "SCardTransmit } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
2011
2012 return status;
2013}
2014
2015LONG WINAPI Emulate_SCardGetTransmitCount(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
2016 LPDWORD pcTransmitCount)
2017{
2018 LONG status = scard_handle_valid(smartcard, hCard);
2019
2020 if (!pcTransmitCount)
2021 status = SCARD_E_INVALID_PARAMETER;
2022
2023 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetTransmitCount { hCard: %p",
2024 (void*)hCard);
2025
2026 if (status == SCARD_S_SUCCESS)
2027 {
2028 SCardHandle* hdl = HashTable_GetItemValue(smartcard->handles, (const void*)hCard);
2029 WINPR_ASSERT(hdl);
2030
2031 *pcTransmitCount = hdl->transmitcount;
2032 }
2033
2034 WLog_Print(smartcard->log, smartcard->log_default_level,
2035 "SCardGetTransmitCount } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2036 status);
2037
2038 return status;
2039}
2040
2041LONG WINAPI Emulate_SCardControl(
2042 SmartcardEmulationContext* smartcard, SCARDHANDLE hCard, DWORD dwControlCode,
2043 LPCVOID lpInBuffer, DWORD cbInBufferSize, LPVOID lpOutBuffer, DWORD cbOutBufferSize,
2044 LPDWORD lpBytesReturned /* NOLINT(readability-non-const-parameter) */)
2045{
2046 LONG status = scard_handle_valid(smartcard, hCard);
2047
2048 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardControl { hCard: %p",
2049 (void*)hCard);
2050
2051 if (status == SCARD_S_SUCCESS)
2052 {
2053 WINPR_UNUSED(dwControlCode);
2054 WINPR_UNUSED(lpInBuffer);
2055 WINPR_UNUSED(cbInBufferSize);
2056 WINPR_UNUSED(lpOutBuffer);
2057 WINPR_UNUSED(cbOutBufferSize);
2058 WINPR_UNUSED(lpBytesReturned);
2059
2060 /* Not required, return not supported */
2061 status = SCARD_E_UNSUPPORTED_FEATURE;
2062 }
2063
2064 WLog_Print(smartcard->log, smartcard->log_default_level,
2065 "SCardControl } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
2066
2067 return status;
2068}
2069
2070LONG WINAPI Emulate_SCardGetAttrib(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
2071 DWORD dwAttrId,
2072 LPBYTE pbAttr /* NOLINT(readability-non-const-parameter) */,
2073 LPDWORD pcbAttrLen /* NOLINT(readability-non-const-parameter) */)
2074{
2075 LONG status = scard_handle_valid(smartcard, hCard);
2076
2077 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetAttrib { hCard: %p",
2078 (void*)hCard);
2079
2080 WINPR_UNUSED(dwAttrId);
2081 WINPR_UNUSED(pbAttr);
2082 WINPR_UNUSED(pcbAttrLen);
2083
2084 /* Not required, return not supported */
2085 if (status == SCARD_S_SUCCESS)
2086 status = SCARD_F_INTERNAL_ERROR;
2087
2088 WLog_Print(smartcard->log, smartcard->log_default_level,
2089 "SCardGetAttrib } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2090 status);
2091
2092 return status;
2093}
2094
2095LONG WINAPI Emulate_SCardSetAttrib(SmartcardEmulationContext* smartcard, SCARDHANDLE hCard,
2096 DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
2097{
2098 LONG status = scard_handle_valid(smartcard, hCard);
2099
2100 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardSetAttrib { hCard: %p",
2101 (void*)hCard);
2102
2103 WINPR_UNUSED(dwAttrId);
2104 WINPR_UNUSED(pbAttr);
2105 WINPR_UNUSED(cbAttrLen);
2106
2107 /* Not required, return not supported */
2108 if (status == SCARD_S_SUCCESS)
2109 status = SCARD_F_INTERNAL_ERROR;
2110
2111 WLog_Print(smartcard->log, smartcard->log_default_level,
2112 "SCardSetAttrib } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2113 status);
2114
2115 return status;
2116}
2117
2118LONG WINAPI Emulate_SCardUIDlgSelectCardA(SmartcardEmulationContext* smartcard,
2119 LPOPENCARDNAMEA_EX pDlgStruc)
2120{
2121 LONG status = 0;
2122
2123 WINPR_ASSERT(smartcard);
2124
2125 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardUIDlgSelectCardA {");
2126
2127 WINPR_UNUSED(pDlgStruc);
2128
2129 /* Not required, return not supported */
2130 status = SCARD_E_UNSUPPORTED_FEATURE;
2131
2132 WLog_Print(smartcard->log, smartcard->log_default_level,
2133 "SCardUIDlgSelectCardA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2134 status);
2135
2136 return status;
2137}
2138
2139LONG WINAPI Emulate_SCardUIDlgSelectCardW(SmartcardEmulationContext* smartcard,
2140 LPOPENCARDNAMEW_EX pDlgStruc)
2141{
2142 LONG status = 0;
2143
2144 WINPR_ASSERT(smartcard);
2145
2146 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardUIDlgSelectCardW {");
2147
2148 WINPR_UNUSED(pDlgStruc);
2149
2150 /* Not required, return not supported */
2151 status = SCARD_E_UNSUPPORTED_FEATURE;
2152
2153 WLog_Print(smartcard->log, smartcard->log_default_level,
2154 "SCardUIDlgSelectCardW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2155 status);
2156
2157 return status;
2158}
2159
2160LONG WINAPI Emulate_GetOpenCardNameA(SmartcardEmulationContext* smartcard,
2161 LPOPENCARDNAMEA pDlgStruc)
2162{
2163 LONG status = 0;
2164
2165 WINPR_ASSERT(smartcard);
2166
2167 WLog_Print(smartcard->log, smartcard->log_default_level, "GetOpenCardNameA {");
2168
2169 WINPR_UNUSED(pDlgStruc);
2170
2171 /* Not required, return not supported */
2172 status = SCARD_E_UNSUPPORTED_FEATURE;
2173
2174 WLog_Print(smartcard->log, smartcard->log_default_level,
2175 "GetOpenCardNameA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2176 status);
2177
2178 return status;
2179}
2180
2181LONG WINAPI Emulate_GetOpenCardNameW(SmartcardEmulationContext* smartcard,
2182 LPOPENCARDNAMEW pDlgStruc)
2183{
2184 LONG status = 0;
2185
2186 WINPR_ASSERT(smartcard);
2187
2188 WLog_Print(smartcard->log, smartcard->log_default_level, "GetOpenCardNameW {");
2189
2190 WINPR_UNUSED(pDlgStruc);
2191
2192 /* Not required, return not supported */
2193 status = SCARD_E_UNSUPPORTED_FEATURE;
2194
2195 WLog_Print(smartcard->log, smartcard->log_default_level,
2196 "GetOpenCardNameW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2197 status);
2198
2199 return status;
2200}
2201
2202LONG WINAPI Emulate_SCardDlgExtendedError(SmartcardEmulationContext* smartcard)
2203{
2204 LONG status = 0;
2205
2206 WINPR_ASSERT(smartcard);
2207
2208 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardDlgExtendedError {");
2209
2210 /* Not required, return not supported */
2211 status = SCARD_E_UNSUPPORTED_FEATURE;
2212
2213 WLog_Print(smartcard->log, smartcard->log_default_level,
2214 "SCardDlgExtendedError } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2215 status);
2216
2217 return status;
2218}
2219
2220LONG WINAPI Emulate_SCardReadCacheA(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
2221 UUID* CardIdentifier, DWORD FreshnessCounter, LPSTR LookupName,
2222 PBYTE Data, DWORD* DataLen)
2223{
2224 DWORD count = 0;
2225 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2226
2227 if (!CardIdentifier || !DataLen)
2228 status = SCARD_E_INVALID_PARAMETER;
2229
2230 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardReadCacheA { hContext: %p",
2231 (void*)hContext);
2232
2233 if (DataLen)
2234 {
2235 count = *DataLen;
2236 *DataLen = 0;
2237 }
2238
2239 if (status == SCARD_S_SUCCESS)
2240 {
2241 SCardCacheItem* data = NULL;
2242 SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
2243 WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
2244
2245 char* id = card_id_and_name_a(CardIdentifier, LookupName);
2246 data = HashTable_GetItemValue(value->cache, id);
2247 free(id);
2248
2249 if (!data)
2250 status = SCARD_W_CACHE_ITEM_NOT_FOUND;
2251 else if (data->freshness != FreshnessCounter)
2252 status = SCARD_W_CACHE_ITEM_STALE;
2253 else
2254 *DataLen = scard_copy_strings(value, Data, count, data->data, data->size);
2255 }
2256
2257 WLog_Print(smartcard->log, smartcard->log_default_level,
2258 "SCardReadCacheA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2259 status);
2260
2261 return status;
2262}
2263
2264LONG WINAPI Emulate_SCardReadCacheW(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
2265 UUID* CardIdentifier, DWORD FreshnessCounter, LPWSTR LookupName,
2266 PBYTE Data, DWORD* DataLen)
2267{
2268 DWORD count = 0;
2269 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2270
2271 if (!CardIdentifier || !DataLen)
2272 status = SCARD_E_INVALID_PARAMETER;
2273
2274 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardReadCacheW { hContext: %p",
2275 (void*)hContext);
2276
2277 if (DataLen)
2278 {
2279 count = *DataLen;
2280 *DataLen = 0;
2281 }
2282
2283 if (status == SCARD_S_SUCCESS)
2284 {
2285 SCardCacheItem* data = NULL;
2286 SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
2287 WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
2288
2289 char* id = card_id_and_name_w(CardIdentifier, LookupName);
2290 data = HashTable_GetItemValue(value->cache, id);
2291 free(id);
2292 if (!data)
2293 status = SCARD_W_CACHE_ITEM_NOT_FOUND;
2294 else if (data->freshness != FreshnessCounter)
2295 status = SCARD_W_CACHE_ITEM_STALE;
2296 else
2297 *DataLen = scard_copy_strings(value, Data, count, data->data, data->size);
2298 }
2299
2300 WLog_Print(smartcard->log, smartcard->log_default_level,
2301 "SCardReadCacheW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2302 status);
2303
2304 return status;
2305}
2306
2307static LONG insert_data(wHashTable* table, DWORD FreshnessCounter, const char* key,
2308 const PBYTE Data, DWORD DataLen)
2309{
2310 BOOL rc = 0;
2311 SCardCacheItem* item = NULL;
2312
2313 WINPR_ASSERT(table);
2314 WINPR_ASSERT(key);
2315
2316 if (DataLen > MAX_CACHE_ITEM_SIZE)
2317 return SCARD_W_CACHE_ITEM_TOO_BIG;
2318
2319 if (HashTable_Count(table) > MAX_CACHE_ITEM_VALUES)
2320 return SCARD_E_WRITE_TOO_MANY;
2321
2322 item = HashTable_GetItemValue(table, key);
2323 if (!item)
2324 {
2325 item = calloc(1, sizeof(SCardCacheItem));
2326 if (!item)
2327 return SCARD_E_NO_MEMORY;
2328
2329 rc = HashTable_Insert(table, key, item);
2330 if (!rc)
2331 {
2332 free(item);
2333 return SCARD_E_NO_MEMORY;
2334 }
2335 }
2336
2337 if (item->freshness > FreshnessCounter)
2338 return SCARD_W_CACHE_ITEM_STALE;
2339 item->freshness = FreshnessCounter;
2340 item->size = DataLen;
2341 memcpy(item->data, Data, DataLen);
2342
2343 // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): HashTable_Insert takes ownership of item
2344 return SCARD_S_SUCCESS;
2345}
2346
2347LONG WINAPI Emulate_SCardWriteCacheA(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
2348 UUID* CardIdentifier, DWORD FreshnessCounter, LPSTR LookupName,
2349 PBYTE Data, DWORD DataLen)
2350{
2351 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2352
2353 if (!CardIdentifier)
2354 status = SCARD_E_INVALID_PARAMETER;
2355
2356 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardWriteCacheA { hContext: %p",
2357 (void*)hContext);
2358
2359 if (status == SCARD_S_SUCCESS)
2360 {
2361 SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
2362 WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
2363
2364 char* id = card_id_and_name_a(CardIdentifier, LookupName);
2365 if (!id)
2366 status = SCARD_E_NO_MEMORY;
2367 else
2368 {
2369 status = insert_data(value->cache, FreshnessCounter, id, Data, DataLen);
2370 free(id);
2371 }
2372 }
2373
2374 WLog_Print(smartcard->log, smartcard->log_default_level,
2375 "SCardWriteCacheA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2376 status);
2377
2378 return status;
2379}
2380
2381LONG WINAPI Emulate_SCardWriteCacheW(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
2382 UUID* CardIdentifier, DWORD FreshnessCounter,
2383 LPWSTR LookupName, PBYTE Data, DWORD DataLen)
2384{
2385 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2386
2387 if (!CardIdentifier)
2388 status = SCARD_E_INVALID_PARAMETER;
2389
2390 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardWriteCacheW { hContext: %p",
2391 (void*)hContext);
2392
2393 if (status == SCARD_S_SUCCESS)
2394 {
2395 SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
2396 WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
2397
2398 char* id = card_id_and_name_w(CardIdentifier, LookupName);
2399 if (!id)
2400 status = SCARD_E_NO_MEMORY;
2401 else
2402 {
2403 status = insert_data(value->cache, FreshnessCounter, id, Data, DataLen);
2404 free(id);
2405 }
2406 }
2407
2408 WLog_Print(smartcard->log, smartcard->log_default_level,
2409 "SCardWriteCacheW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2410 status);
2411
2412 return status;
2413}
2414
2415LONG WINAPI Emulate_SCardGetReaderIconA(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
2416 LPCSTR szReaderName, LPBYTE pbIcon, LPDWORD pcbIcon)
2417{
2418 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2419
2420 if (!szReaderName || !pcbIcon)
2421 status = SCARD_E_INVALID_PARAMETER;
2422
2423 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetReaderIconA { hContext: %p",
2424 (void*)hContext);
2425
2426 if (status == SCARD_S_SUCCESS)
2427 status = scard_reader_name_valid_a(smartcard, hContext, szReaderName);
2428
2429 if (status == SCARD_S_SUCCESS)
2430 {
2431 SCardContext* ctx = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
2432 WINPR_ASSERT(ctx);
2433
2434 if (pbIcon)
2435 *pcbIcon = scard_copy_strings(ctx, pbIcon, *pcbIcon, resources_FreeRDP_ico,
2436 resources_FreeRDP_ico_len);
2437 else
2438 *pcbIcon = resources_FreeRDP_ico_len;
2439 }
2440
2441 WLog_Print(smartcard->log, smartcard->log_default_level,
2442 "SCardGetReaderIconA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2443 status);
2444
2445 return status;
2446}
2447
2448LONG WINAPI Emulate_SCardGetReaderIconW(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
2449 LPCWSTR szReaderName, LPBYTE pbIcon, LPDWORD pcbIcon)
2450{
2451 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2452
2453 if (!szReaderName || !pcbIcon)
2454 status = SCARD_E_INVALID_PARAMETER;
2455
2456 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetReaderIconW { hContext: %p",
2457 (void*)hContext);
2458
2459 if (status == SCARD_S_SUCCESS)
2460 status = scard_reader_name_valid_w(smartcard, hContext, szReaderName);
2461
2462 if (status == SCARD_S_SUCCESS)
2463 {
2464 SCardContext* ctx = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
2465 WINPR_ASSERT(ctx);
2466
2467 if (pbIcon)
2468 *pcbIcon = scard_copy_strings(ctx, pbIcon, *pcbIcon, resources_FreeRDP_ico,
2469 resources_FreeRDP_ico_len);
2470 else
2471 *pcbIcon = resources_FreeRDP_ico_len;
2472 }
2473
2474 WLog_Print(smartcard->log, smartcard->log_default_level,
2475 "SCardGetReaderIconW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2476 status);
2477
2478 return status;
2479}
2480
2481LONG WINAPI Emulate_SCardGetDeviceTypeIdA(SmartcardEmulationContext* smartcard,
2482 SCARDCONTEXT hContext, LPCSTR szReaderName,
2483 LPDWORD pdwDeviceTypeId)
2484{
2485 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2486
2487 if (!pdwDeviceTypeId)
2488 status = SCARD_E_INVALID_PARAMETER;
2489
2490 if (status == SCARD_S_SUCCESS)
2491 status = scard_reader_name_valid_a(smartcard, hContext, szReaderName);
2492
2493 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetDeviceTypeIdA { hContext: %p",
2494 (void*)hContext);
2495
2496 if (status == SCARD_S_SUCCESS)
2497 {
2498 *pdwDeviceTypeId = SCARD_READER_TYPE_USB; // SCARD_READER_TYPE_TPM
2499 }
2500
2501 WLog_Print(smartcard->log, smartcard->log_default_level,
2502 "SCardGetDeviceTypeIdA } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2503 status);
2504
2505 return status;
2506}
2507
2508LONG WINAPI Emulate_SCardGetDeviceTypeIdW(SmartcardEmulationContext* smartcard,
2509 SCARDCONTEXT hContext, LPCWSTR szReaderName,
2510 LPDWORD pdwDeviceTypeId)
2511{
2512 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2513
2514 if (!pdwDeviceTypeId)
2515 status = SCARD_E_INVALID_PARAMETER;
2516
2517 if (status == SCARD_S_SUCCESS)
2518 status = scard_reader_name_valid_w(smartcard, hContext, szReaderName);
2519
2520 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardGetDeviceTypeIdW { hContext: %p",
2521 (void*)hContext);
2522
2523 if (status == SCARD_S_SUCCESS)
2524 {
2525 *pdwDeviceTypeId = SCARD_READER_TYPE_USB; // SCARD_READER_TYPE_TPM
2526 }
2527
2528 WLog_Print(smartcard->log, smartcard->log_default_level,
2529 "SCardGetDeviceTypeIdW } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status),
2530 status);
2531
2532 return status;
2533}
2534
2535LONG WINAPI Emulate_SCardGetReaderDeviceInstanceIdA(
2536 SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext, LPCSTR szReaderName,
2537 LPSTR szDeviceInstanceId /* NOLINT(readability-non-const-parameter) */,
2538 LPDWORD pcchDeviceInstanceId /* NOLINT(readability-non-const-parameter) */)
2539{
2540 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2541
2542 if (status == SCARD_S_SUCCESS)
2543 status = scard_reader_name_valid_a(smartcard, hContext, szReaderName);
2544
2545 WLog_Print(smartcard->log, smartcard->log_default_level,
2546 "SCardGetReaderDeviceInstanceIdA { hContext: %p", (void*)hContext);
2547
2548 WINPR_UNUSED(szDeviceInstanceId);
2549 WINPR_UNUSED(pcchDeviceInstanceId);
2550
2551 /* Not required, return not supported */
2552 if (status == SCARD_S_SUCCESS)
2553 status = SCARD_E_UNSUPPORTED_FEATURE;
2554
2555 WLog_Print(smartcard->log, smartcard->log_default_level,
2556 "SCardGetReaderDeviceInstanceIdA } status: %s (0x%08" PRIX32 ")",
2557 SCardGetErrorString(status), status);
2558
2559 return status;
2560}
2561
2562LONG WINAPI Emulate_SCardGetReaderDeviceInstanceIdW(
2563 SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext, LPCWSTR szReaderName,
2564 LPWSTR szDeviceInstanceId /* NOLINT(readability-non-const-parameter) */,
2565 LPDWORD pcchDeviceInstanceId /* NOLINT(readability-non-const-parameter) */)
2566{
2567 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2568
2569 if (status == SCARD_S_SUCCESS)
2570 status = scard_reader_name_valid_w(smartcard, hContext, szReaderName);
2571
2572 WLog_Print(smartcard->log, smartcard->log_default_level,
2573 "SCardGetReaderDeviceInstanceIdW { hContext: %p", (void*)hContext);
2574
2575 WINPR_UNUSED(szDeviceInstanceId);
2576 WINPR_UNUSED(pcchDeviceInstanceId);
2577
2578 /* Not required, return not supported */
2579 if (status == SCARD_S_SUCCESS)
2580 status = SCARD_E_UNSUPPORTED_FEATURE;
2581
2582 WLog_Print(smartcard->log, smartcard->log_default_level,
2583 "SCardGetReaderDeviceInstanceIdW } status: %s (0x%08" PRIX32 ")",
2584 SCardGetErrorString(status), status);
2585
2586 return status;
2587}
2588
2589LONG WINAPI Emulate_SCardListReadersWithDeviceInstanceIdA(
2590 SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext, LPCSTR szDeviceInstanceId,
2591 LPSTR mszReaders /* NOLINT(readability-non-const-parameter) */,
2592 LPDWORD pcchReaders /* NOLINT(readability-non-const-parameter) */)
2593{
2594 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2595
2596 WLog_Print(smartcard->log, smartcard->log_default_level,
2597 "SCardListReadersWithDeviceInstanceIdA { hContext: %p", (void*)hContext);
2598
2599 WINPR_UNUSED(szDeviceInstanceId);
2600 WINPR_UNUSED(mszReaders);
2601 WINPR_UNUSED(pcchReaders);
2602
2603 /* Not required, return not supported */
2604 if (status == SCARD_S_SUCCESS)
2605 status = SCARD_E_UNSUPPORTED_FEATURE;
2606
2607 WLog_Print(smartcard->log, smartcard->log_default_level,
2608 "SCardListReadersWithDeviceInstanceIdA } status: %s (0x%08" PRIX32 ")",
2609 SCardGetErrorString(status), status);
2610
2611 return status;
2612}
2613
2614LONG WINAPI Emulate_SCardListReadersWithDeviceInstanceIdW(
2615 SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext, LPCWSTR szDeviceInstanceId,
2616 LPWSTR mszReaders /* NOLINT(readability-non-const-parameter) */, LPDWORD pcchReaders)
2617{
2618 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2619
2620 WLog_Print(smartcard->log, smartcard->log_default_level,
2621 "SCardListReadersWithDeviceInstanceIdW { hContext: %p", (void*)hContext);
2622
2623 WINPR_UNUSED(szDeviceInstanceId);
2624 WINPR_UNUSED(mszReaders);
2625 WINPR_UNUSED(pcchReaders);
2626
2627 /* Not required, return not supported */
2628 if (status == SCARD_S_SUCCESS)
2629 status = SCARD_E_UNSUPPORTED_FEATURE;
2630
2631 WLog_Print(smartcard->log, smartcard->log_default_level,
2632 "SCardListReadersWithDeviceInstanceIdW } status: %s (0x%08" PRIX32 ")",
2633 SCardGetErrorString(status), status);
2634
2635 return status;
2636}
2637
2638LONG WINAPI Emulate_SCardAudit(SmartcardEmulationContext* smartcard, SCARDCONTEXT hContext,
2639 DWORD dwEvent)
2640{
2641 LONG status = Emulate_SCardIsValidContext(smartcard, hContext);
2642
2643 WINPR_UNUSED(dwEvent);
2644
2645 WLog_Print(smartcard->log, smartcard->log_default_level, "SCardAudit { hContext: %p",
2646 (void*)hContext);
2647
2648 // TODO: Implement
2649 if (status == SCARD_S_SUCCESS)
2650 status = SCARD_E_UNSUPPORTED_FEATURE;
2651
2652 WLog_Print(smartcard->log, smartcard->log_default_level,
2653 "SCardAudit } status: %s (0x%08" PRIX32 ")", SCardGetErrorString(status), status);
2654
2655 return status;
2656}
2657
2658static BOOL context_equals(const void* pva, const void* pvb)
2659{
2660 const SCARDCONTEXT a = (const SCARDCONTEXT)pva;
2661 const SCARDCONTEXT b = (const SCARDCONTEXT)pvb;
2662 if (!a && !b)
2663 return TRUE;
2664 if (!a || !b)
2665 return FALSE;
2666
2667 return a == b;
2668}
2669
2670static BOOL handle_equals(const void* pva, const void* pvb)
2671{
2672 const SCARDHANDLE a = (const SCARDHANDLE)pva;
2673 const SCARDHANDLE b = (const SCARDHANDLE)pvb;
2674 if (!a && !b)
2675 return TRUE;
2676 if (!a || !b)
2677 return FALSE;
2678
2679 return a == b;
2680}
2681
2682SmartcardEmulationContext* Emulate_New(const rdpSettings* settings)
2683{
2684 SmartcardEmulationContext* smartcard = NULL;
2685
2686 WINPR_ASSERT(settings);
2687
2688 smartcard = calloc(1, sizeof(SmartcardEmulationContext));
2689 if (!smartcard)
2690 goto fail;
2691
2692 smartcard->settings = settings;
2693 smartcard->log = WLog_Get("EmulateSCard");
2694 if (!smartcard->log)
2695 goto fail;
2696 smartcard->log_default_level = WLOG_TRACE;
2697
2698 smartcard->contexts = HashTable_New(FALSE);
2699 if (!smartcard->contexts)
2700 goto fail;
2701 else
2702 {
2703 wObject* obj = HashTable_KeyObject(smartcard->contexts);
2704 WINPR_ASSERT(obj);
2705 obj->fnObjectEquals = context_equals;
2706 }
2707 if (!smartcard->contexts)
2708 goto fail;
2709 else
2710 {
2711 wObject* obj = HashTable_ValueObject(smartcard->contexts);
2712 WINPR_ASSERT(obj);
2713 obj->fnObjectFree = scard_context_free;
2714 }
2715
2716 smartcard->handles = HashTable_New(FALSE);
2717 if (!smartcard->handles)
2718 goto fail;
2719 else
2720 {
2721 wObject* obj = HashTable_KeyObject(smartcard->handles);
2722 WINPR_ASSERT(obj);
2723 obj->fnObjectEquals = handle_equals;
2724 }
2725 if (!smartcard->handles)
2726 goto fail;
2727 else
2728 {
2729 wObject* obj = HashTable_ValueObject(smartcard->handles);
2730 WINPR_ASSERT(obj);
2731 obj->fnObjectFree = scard_handle_free;
2732 }
2733
2734 return smartcard;
2735
2736fail:
2737 WINPR_PRAGMA_DIAG_PUSH
2738 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2739 Emulate_Free(smartcard);
2740 WINPR_PRAGMA_DIAG_POP
2741 return NULL;
2742}
2743
2744void Emulate_Free(SmartcardEmulationContext* context)
2745{
2746 if (!context)
2747 return;
2748
2749 HashTable_Free(context->handles);
2750 HashTable_Free(context->contexts);
2751 free(context);
2752}
2753
2754BOOL Emulate_IsConfigured(SmartcardEmulationContext* context)
2755{
2756 BOOL rc = FALSE;
2757 vgidsContext* vgids = NULL;
2758 const char* pem = NULL;
2759 const char* key = NULL;
2760 const char* pin = NULL;
2761
2762 WINPR_ASSERT(context);
2763
2764 pem = freerdp_settings_get_string(context->settings, FreeRDP_SmartcardCertificate);
2765 key = freerdp_settings_get_string(context->settings, FreeRDP_SmartcardPrivateKey);
2766 pin = freerdp_settings_get_string(context->settings, FreeRDP_Password);
2767
2768 /* Cache result only, if no initialization arguments changed. */
2769 if ((context->pem == pem) && (context->key == key) && (context->pin == pin))
2770 return context->configured;
2771
2772 context->pem = pem;
2773 context->key = key;
2774 context->pin = pin;
2775
2776 vgids = vgids_new();
2777 if (vgids)
2778 rc = vgids_init(vgids, context->pem, context->key, context->pin);
2779 vgids_free(vgids);
2780
2781 context->configured = rc;
2782 return rc;
2783}
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:252
This struct contains function pointer to initialize/free objects.
Definition collections.h:57