Coverage Report

Created: 2026-03-04 06:17

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