Coverage Report

Created: 2025-07-01 06:46

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