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