Coverage Report

Created: 2025-08-26 06:37

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