Coverage Report

Created: 2026-09-14 06:32

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