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