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