Coverage Report

Created: 2024-09-08 06:20

/src/FreeRDP/libfreerdp/utils/smartcard_call.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Smartcard Device Service Virtual Channel
4
 *
5
 * Copyright (C) Alexi Volkov <alexi@myrealbox.com> 2006
6
 * Copyright 2011 O.S. Systems Software Ltda.
7
 * Copyright 2011 Anthony Tong <atong@trustedcs.com>
8
 * Copyright 2015 Thincast Technologies GmbH
9
 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
10
 * Copyright 2017 Armin Novak <armin.novak@thincast.com>
11
 * Copyright 2017 Thincast Technologies GmbH
12
 *
13
 * Licensed under the Apache License, Version 2.0 (the "License");
14
 * you may not use this file except in compliance with the License.
15
 * You may obtain a copy of the License at
16
 *
17
 *     http://www.apache.org/licenses/LICENSE-2.0
18
 *
19
 * Unless required by applicable law or agreed to in writing, software
20
 * distributed under the License is distributed on an "AS IS" BASIS,
21
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
 * See the License for the specific language governing permissions and
23
 * limitations under the License.
24
 */
25
26
#include <freerdp/config.h>
27
28
#include <winpr/assert.h>
29
30
#include <winpr/crt.h>
31
#include <winpr/print.h>
32
#include <winpr/stream.h>
33
#include <winpr/library.h>
34
#include <winpr/smartcard.h>
35
36
#include <freerdp/freerdp.h>
37
#include <freerdp/channels/rdpdr.h>
38
#include <freerdp/channels/scard.h>
39
40
#include <freerdp/utils/rdpdr_utils.h>
41
#include <freerdp/utils/smartcard_pack.h>
42
#include <freerdp/utils/smartcard_call.h>
43
44
#include <freerdp/log.h>
45
0
#define TAG FREERDP_TAG("utils.smartcard.call")
46
47
#if defined(WITH_SMARTCARD_EMULATE)
48
#include <freerdp/emulate/scard/smartcard_emulate.h>
49
50
#define str(x) #x
51
#define wrap(ctx, fkt, ...)                                             \
52
0
  ctx->useEmulatedCard ? Emulate_##fkt(ctx->emulation, ##__VA_ARGS__) \
53
0
                       : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
54
0
#define wrap_ptr(ctx, fkt, ...) wrap(ctx, fkt, ##__VA_ARGS__)
55
#else
56
#define wrap(ctx, fkt, ...) \
57
  ctx->useEmulatedCard ? SCARD_F_INTERNAL_ERROR : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
58
#define wrap_ptr(ctx, fkt, ...) \
59
  ctx->useEmulatedCard ? NULL : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
60
#endif
61
62
struct s_scard_call_context
63
{
64
  BOOL useEmulatedCard;
65
  HANDLE StartedEvent;
66
  wLinkedList* names;
67
  wHashTable* rgSCardContextList;
68
#if defined(WITH_SMARTCARD_EMULATE)
69
  SmartcardEmulationContext* emulation;
70
#endif
71
  HANDLE hWinSCardLibrary;
72
  SCardApiFunctionTable WinSCardApi;
73
  const SCardApiFunctionTable* pWinSCardApi;
74
  HANDLE stopEvent;
75
  void* userdata;
76
77
  void* (*fn_new)(void*, SCARDCONTEXT);
78
  void (*fn_free)(void*);
79
};
80
81
struct s_scard_context_element
82
{
83
  void* context;
84
  void (*fn_free)(void*);
85
};
86
87
static void context_free(void* arg);
88
89
static LONG smartcard_EstablishContext_Call(scard_call_context* smartcard, wStream* out,
90
                                            SMARTCARD_OPERATION* operation)
91
0
{
92
0
  LONG status = 0;
93
0
  SCARDCONTEXT hContext = { 0 };
94
0
  EstablishContext_Return ret = { 0 };
95
0
  EstablishContext_Call* call = &operation->call.establishContext;
96
0
  status = ret.ReturnCode =
97
0
      wrap(smartcard, SCardEstablishContext, call->dwScope, NULL, NULL, &hContext);
98
99
0
  if (ret.ReturnCode == SCARD_S_SUCCESS)
100
0
  {
101
0
    const void* key = (void*)(size_t)hContext;
102
0
    struct s_scard_context_element* pContext =
103
0
        calloc(1, sizeof(struct s_scard_context_element));
104
0
    if (!pContext)
105
0
      return STATUS_NO_MEMORY;
106
107
0
    pContext->fn_free = smartcard->fn_free;
108
109
0
    if (smartcard->fn_new)
110
0
    {
111
0
      pContext->context = smartcard->fn_new(smartcard->userdata, hContext);
112
0
      if (!pContext->context)
113
0
      {
114
0
        free(pContext);
115
0
        return STATUS_NO_MEMORY;
116
0
      }
117
0
    }
118
119
0
    if (!HashTable_Insert(smartcard->rgSCardContextList, key, (void*)pContext))
120
0
    {
121
0
      WLog_ERR(TAG, "ListDictionary_Add failed!");
122
0
      context_free(pContext);
123
0
      return STATUS_INTERNAL_ERROR;
124
0
    }
125
0
  }
126
0
  else
127
0
  {
128
0
    return scard_log_status_error(TAG, "SCardEstablishContext", status);
129
0
  }
130
131
  // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): HashTable_Insert takes ownership of pContext
132
0
  smartcard_scard_context_native_to_redir(&(ret.hContext), hContext);
133
134
0
  status = smartcard_pack_establish_context_return(out, &ret);
135
0
  if (status != SCARD_S_SUCCESS)
136
0
  {
137
0
    return scard_log_status_error(TAG, "smartcard_pack_establish_context_return", status);
138
0
  }
139
140
0
  return ret.ReturnCode;
141
0
}
142
143
static LONG smartcard_ReleaseContext_Call(scard_call_context* smartcard, wStream* out,
144
                                          SMARTCARD_OPERATION* operation)
145
0
{
146
0
  Long_Return ret = { 0 };
147
148
0
  WINPR_ASSERT(smartcard);
149
0
  WINPR_ASSERT(out);
150
0
  WINPR_ASSERT(operation);
151
152
0
  ret.ReturnCode = wrap(smartcard, SCardReleaseContext, operation->hContext);
153
154
0
  if (ret.ReturnCode == SCARD_S_SUCCESS)
155
0
    HashTable_Remove(smartcard->rgSCardContextList, (void*)operation->hContext);
156
0
  else
157
0
  {
158
0
    return scard_log_status_error(TAG, "SCardReleaseContext", ret.ReturnCode);
159
0
  }
160
161
0
  smartcard_trace_long_return(&ret, "ReleaseContext");
162
0
  return ret.ReturnCode;
163
0
}
164
165
static LONG smartcard_IsValidContext_Call(scard_call_context* smartcard, wStream* out,
166
                                          SMARTCARD_OPERATION* operation)
167
0
{
168
0
  Long_Return ret = { 0 };
169
170
0
  WINPR_ASSERT(smartcard);
171
0
  WINPR_ASSERT(out);
172
0
  WINPR_ASSERT(operation);
173
174
0
  ret.ReturnCode = wrap(smartcard, SCardIsValidContext, operation->hContext);
175
0
  smartcard_trace_long_return(&ret, "IsValidContext");
176
0
  return ret.ReturnCode;
177
0
}
178
179
static LONG smartcard_ListReaderGroupsA_Call(scard_call_context* smartcard, wStream* out,
180
                                             SMARTCARD_OPERATION* operation)
181
0
{
182
0
  LONG status = 0;
183
0
  ListReaderGroups_Return ret = { 0 };
184
0
  LPSTR mszGroups = NULL;
185
0
  DWORD cchGroups = 0;
186
187
0
  WINPR_ASSERT(smartcard);
188
0
  WINPR_ASSERT(out);
189
0
  WINPR_ASSERT(operation);
190
191
0
  cchGroups = SCARD_AUTOALLOCATE;
192
0
  ret.ReturnCode =
193
0
      wrap(smartcard, SCardListReaderGroupsA, operation->hContext, (LPSTR)&mszGroups, &cchGroups);
194
0
  if (cchGroups == SCARD_AUTOALLOCATE)
195
0
    return SCARD_F_UNKNOWN_ERROR;
196
197
0
  ret.msz = (BYTE*)mszGroups;
198
0
  ret.cBytes = cchGroups;
199
200
0
  status = smartcard_pack_list_reader_groups_return(out, &ret, FALSE);
201
202
0
  if (status != SCARD_S_SUCCESS)
203
0
    return status;
204
205
0
  if (mszGroups)
206
0
    wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
207
208
0
  return ret.ReturnCode;
209
0
}
210
211
static LONG smartcard_ListReaderGroupsW_Call(scard_call_context* smartcard, wStream* out,
212
                                             SMARTCARD_OPERATION* operation)
213
0
{
214
0
  LONG status = 0;
215
0
  ListReaderGroups_Return ret = { 0 };
216
0
  LPWSTR mszGroups = NULL;
217
0
  DWORD cchGroups = 0;
218
219
0
  WINPR_ASSERT(smartcard);
220
0
  WINPR_ASSERT(out);
221
0
  WINPR_ASSERT(operation);
222
223
0
  cchGroups = SCARD_AUTOALLOCATE;
224
0
  status = ret.ReturnCode = wrap(smartcard, SCardListReaderGroupsW, operation->hContext,
225
0
                                 (LPWSTR)&mszGroups, &cchGroups);
226
0
  if (cchGroups == SCARD_AUTOALLOCATE)
227
0
    return SCARD_F_UNKNOWN_ERROR;
228
229
0
  ret.msz = (BYTE*)mszGroups;
230
0
  ret.cBytes = cchGroups * sizeof(WCHAR);
231
232
0
  if (status != SCARD_S_SUCCESS)
233
0
    return status;
234
235
0
  status = smartcard_pack_list_reader_groups_return(out, &ret, TRUE);
236
237
0
  if (status != SCARD_S_SUCCESS)
238
0
    return status;
239
240
0
  if (mszGroups)
241
0
    wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
242
243
0
  return ret.ReturnCode;
244
0
}
245
246
static BOOL filter_match(wLinkedList* list, LPCSTR reader, size_t readerLen)
247
0
{
248
0
  if (readerLen < 1)
249
0
    return FALSE;
250
251
0
  LinkedList_Enumerator_Reset(list);
252
253
0
  while (LinkedList_Enumerator_MoveNext(list))
254
0
  {
255
0
    const char* filter = LinkedList_Enumerator_Current(list);
256
257
0
    if (filter)
258
0
    {
259
0
      if (strstr(reader, filter) != NULL)
260
0
        return TRUE;
261
0
    }
262
0
  }
263
264
0
  return FALSE;
265
0
}
266
267
static DWORD filter_device_by_name_a(wLinkedList* list, LPSTR* mszReaders, DWORD cchReaders)
268
0
{
269
0
  size_t rpos = 0;
270
0
  size_t wpos = 0;
271
272
0
  if (*mszReaders == NULL || LinkedList_Count(list) < 1)
273
0
    return cchReaders;
274
275
0
  do
276
0
  {
277
0
    LPCSTR rreader = &(*mszReaders)[rpos];
278
0
    LPSTR wreader = &(*mszReaders)[wpos];
279
0
    size_t readerLen = strnlen(rreader, cchReaders - rpos);
280
281
0
    rpos += readerLen + 1;
282
283
0
    if (filter_match(list, rreader, readerLen))
284
0
    {
285
0
      if (rreader != wreader)
286
0
        memmove(wreader, rreader, readerLen + 1);
287
288
0
      wpos += readerLen + 1;
289
0
    }
290
0
  } while (rpos < cchReaders);
291
292
  /* this string must be double 0 terminated */
293
0
  if (rpos != wpos)
294
0
  {
295
0
    if (wpos >= cchReaders)
296
0
      return 0;
297
298
0
    (*mszReaders)[wpos++] = '\0';
299
0
  }
300
301
0
  return (DWORD)wpos;
302
0
}
303
304
static DWORD filter_device_by_name_w(wLinkedList* list, LPWSTR* mszReaders, DWORD cchReaders)
305
0
{
306
0
  DWORD rc = 0;
307
0
  LPSTR readers = NULL;
308
309
0
  if (LinkedList_Count(list) < 1)
310
0
    return cchReaders;
311
312
0
  readers = ConvertMszWCharNToUtf8Alloc(*mszReaders, cchReaders, NULL);
313
314
0
  if (!readers)
315
0
  {
316
0
    free(readers);
317
0
    return 0;
318
0
  }
319
320
0
  free(*mszReaders);
321
0
  *mszReaders = NULL;
322
0
  rc = filter_device_by_name_a(list, &readers, cchReaders);
323
324
0
  *mszReaders = ConvertMszUtf8NToWCharAlloc(readers, rc, NULL);
325
0
  if (!*mszReaders)
326
0
    rc = 0;
327
328
0
  free(readers);
329
0
  return rc;
330
0
}
331
332
static LONG smartcard_ListReadersA_Call(scard_call_context* smartcard, wStream* out,
333
                                        SMARTCARD_OPERATION* operation)
334
0
{
335
0
  LONG status = 0;
336
0
  ListReaders_Return ret = { 0 };
337
0
  LPSTR mszReaders = NULL;
338
0
  DWORD cchReaders = 0;
339
0
  ListReaders_Call* call = NULL;
340
341
0
  WINPR_ASSERT(smartcard);
342
0
  WINPR_ASSERT(out);
343
0
  WINPR_ASSERT(operation);
344
345
0
  call = &operation->call.listReaders;
346
0
  cchReaders = SCARD_AUTOALLOCATE;
347
0
  status = ret.ReturnCode = wrap(smartcard, SCardListReadersA, operation->hContext,
348
0
                                 (LPCSTR)call->mszGroups, (LPSTR)&mszReaders, &cchReaders);
349
0
  if (cchReaders == SCARD_AUTOALLOCATE)
350
0
    return SCARD_F_UNKNOWN_ERROR;
351
352
0
  if (status != SCARD_S_SUCCESS)
353
0
  {
354
0
    return scard_log_status_error(TAG, "SCardListReadersA", status);
355
0
  }
356
357
0
  cchReaders = filter_device_by_name_a(smartcard->names, &mszReaders, cchReaders);
358
0
  ret.msz = (BYTE*)mszReaders;
359
0
  ret.cBytes = cchReaders;
360
361
0
  status = smartcard_pack_list_readers_return(out, &ret, FALSE);
362
0
  if (status != SCARD_S_SUCCESS)
363
0
  {
364
0
    return scard_log_status_error(TAG, "smartcard_pack_list_readers_return", status);
365
0
  }
366
367
0
  if (mszReaders)
368
0
    wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaders);
369
370
0
  if (status != SCARD_S_SUCCESS)
371
0
    return status;
372
373
0
  return ret.ReturnCode;
374
0
}
375
376
static LONG smartcard_ListReadersW_Call(scard_call_context* smartcard, wStream* out,
377
                                        SMARTCARD_OPERATION* operation)
378
0
{
379
0
  LONG status = 0;
380
0
  ListReaders_Return ret = { 0 };
381
0
  DWORD cchReaders = 0;
382
0
  ListReaders_Call* call = NULL;
383
0
  union
384
0
  {
385
0
    const BYTE* bp;
386
0
    const char* sz;
387
0
    const WCHAR* wz;
388
0
  } string;
389
0
  union
390
0
  {
391
0
    WCHAR** ppw;
392
0
    WCHAR* pw;
393
0
    CHAR* pc;
394
0
    BYTE* pb;
395
0
  } mszReaders;
396
397
0
  WINPR_ASSERT(smartcard);
398
0
  WINPR_ASSERT(operation);
399
400
0
  call = &operation->call.listReaders;
401
402
0
  string.bp = call->mszGroups;
403
0
  cchReaders = SCARD_AUTOALLOCATE;
404
0
  status = ret.ReturnCode = wrap(smartcard, SCardListReadersW, operation->hContext, string.wz,
405
0
                                 (LPWSTR)&mszReaders.pw, &cchReaders);
406
0
  if (cchReaders == SCARD_AUTOALLOCATE)
407
0
    return SCARD_F_UNKNOWN_ERROR;
408
409
0
  if (status != SCARD_S_SUCCESS)
410
0
    return scard_log_status_error(TAG, "SCardListReadersW", status);
411
412
0
  cchReaders = filter_device_by_name_w(smartcard->names, &mszReaders.pw, cchReaders);
413
0
  ret.msz = mszReaders.pb;
414
0
  ret.cBytes = cchReaders * sizeof(WCHAR);
415
0
  status = smartcard_pack_list_readers_return(out, &ret, TRUE);
416
417
0
  if (mszReaders.pb)
418
0
    wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaders.pb);
419
420
0
  if (status != SCARD_S_SUCCESS)
421
0
    return status;
422
423
0
  return ret.ReturnCode;
424
0
}
425
426
static LONG smartcard_IntroduceReaderGroupA_Call(scard_call_context* smartcard, wStream* out,
427
                                                 SMARTCARD_OPERATION* operation)
428
0
{
429
0
  Long_Return ret = { 0 };
430
0
  ContextAndStringA_Call* call = NULL;
431
432
0
  WINPR_ASSERT(smartcard);
433
0
  WINPR_ASSERT(out);
434
0
  WINPR_ASSERT(operation);
435
436
0
  call = &operation->call.contextAndStringA;
437
0
  ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupA, operation->hContext, call->sz);
438
0
  scard_log_status_error(TAG, "SCardIntroduceReaderGroupA", ret.ReturnCode);
439
0
  smartcard_trace_long_return(&ret, "IntroduceReaderGroupA");
440
0
  return ret.ReturnCode;
441
0
}
442
443
static LONG smartcard_IntroduceReaderGroupW_Call(scard_call_context* smartcard, wStream* out,
444
                                                 SMARTCARD_OPERATION* operation)
445
0
{
446
0
  Long_Return ret = { 0 };
447
0
  ContextAndStringW_Call* call = NULL;
448
449
0
  WINPR_ASSERT(smartcard);
450
0
  WINPR_ASSERT(out);
451
0
  WINPR_ASSERT(operation);
452
453
0
  call = &operation->call.contextAndStringW;
454
0
  ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupW, operation->hContext, call->sz);
455
0
  scard_log_status_error(TAG, "SCardIntroduceReaderGroupW", ret.ReturnCode);
456
0
  smartcard_trace_long_return(&ret, "IntroduceReaderGroupW");
457
0
  return ret.ReturnCode;
458
0
}
459
460
static LONG smartcard_IntroduceReaderA_Call(scard_call_context* smartcard, wStream* out,
461
                                            SMARTCARD_OPERATION* operation)
462
0
{
463
0
  Long_Return ret = { 0 };
464
0
  ContextAndTwoStringA_Call* call = NULL;
465
466
0
  WINPR_ASSERT(smartcard);
467
0
  WINPR_ASSERT(out);
468
0
  WINPR_ASSERT(operation);
469
470
0
  call = &operation->call.contextAndTwoStringA;
471
0
  ret.ReturnCode =
472
0
      wrap(smartcard, SCardIntroduceReaderA, operation->hContext, call->sz1, call->sz2);
473
0
  scard_log_status_error(TAG, "SCardIntroduceReaderA", ret.ReturnCode);
474
0
  smartcard_trace_long_return(&ret, "IntroduceReaderA");
475
0
  return ret.ReturnCode;
476
0
}
477
478
static LONG smartcard_IntroduceReaderW_Call(scard_call_context* smartcard, wStream* out,
479
                                            SMARTCARD_OPERATION* operation)
480
0
{
481
0
  Long_Return ret = { 0 };
482
0
  ContextAndTwoStringW_Call* call = NULL;
483
484
0
  WINPR_ASSERT(smartcard);
485
0
  WINPR_ASSERT(out);
486
0
  WINPR_ASSERT(operation);
487
488
0
  call = &operation->call.contextAndTwoStringW;
489
0
  ret.ReturnCode =
490
0
      wrap(smartcard, SCardIntroduceReaderW, operation->hContext, call->sz1, call->sz2);
491
0
  scard_log_status_error(TAG, "SCardIntroduceReaderW", ret.ReturnCode);
492
0
  smartcard_trace_long_return(&ret, "IntroduceReaderW");
493
0
  return ret.ReturnCode;
494
0
}
495
496
static LONG smartcard_ForgetReaderA_Call(scard_call_context* smartcard, wStream* out,
497
                                         SMARTCARD_OPERATION* operation)
498
0
{
499
0
  Long_Return ret = { 0 };
500
0
  ContextAndStringA_Call* call = NULL;
501
502
0
  WINPR_ASSERT(smartcard);
503
0
  WINPR_ASSERT(out);
504
0
  WINPR_ASSERT(operation);
505
506
0
  call = &operation->call.contextAndStringA;
507
0
  ret.ReturnCode = wrap(smartcard, SCardForgetReaderA, operation->hContext, call->sz);
508
0
  scard_log_status_error(TAG, "SCardForgetReaderA", ret.ReturnCode);
509
0
  smartcard_trace_long_return(&ret, "SCardForgetReaderA");
510
0
  return ret.ReturnCode;
511
0
}
512
513
static LONG smartcard_ForgetReaderW_Call(scard_call_context* smartcard, wStream* out,
514
                                         SMARTCARD_OPERATION* operation)
515
0
{
516
0
  Long_Return ret = { 0 };
517
0
  ContextAndStringW_Call* call = NULL;
518
519
0
  WINPR_ASSERT(smartcard);
520
0
  WINPR_ASSERT(out);
521
0
  WINPR_ASSERT(operation);
522
523
0
  call = &operation->call.contextAndStringW;
524
0
  ret.ReturnCode = wrap(smartcard, SCardForgetReaderW, operation->hContext, call->sz);
525
0
  scard_log_status_error(TAG, "SCardForgetReaderW", ret.ReturnCode);
526
0
  smartcard_trace_long_return(&ret, "SCardForgetReaderW");
527
0
  return ret.ReturnCode;
528
0
}
529
530
static LONG smartcard_AddReaderToGroupA_Call(scard_call_context* smartcard, wStream* out,
531
                                             SMARTCARD_OPERATION* operation)
532
0
{
533
0
  Long_Return ret = { 0 };
534
0
  ContextAndTwoStringA_Call* call = NULL;
535
536
0
  WINPR_ASSERT(smartcard);
537
0
  WINPR_ASSERT(out);
538
0
  WINPR_ASSERT(operation);
539
540
0
  call = &operation->call.contextAndTwoStringA;
541
0
  ret.ReturnCode =
542
0
      wrap(smartcard, SCardAddReaderToGroupA, operation->hContext, call->sz1, call->sz2);
543
0
  scard_log_status_error(TAG, "SCardAddReaderToGroupA", ret.ReturnCode);
544
0
  smartcard_trace_long_return(&ret, "SCardAddReaderToGroupA");
545
0
  return ret.ReturnCode;
546
0
}
547
548
static LONG smartcard_AddReaderToGroupW_Call(scard_call_context* smartcard, wStream* out,
549
                                             SMARTCARD_OPERATION* operation)
550
0
{
551
0
  Long_Return ret = { 0 };
552
0
  ContextAndTwoStringW_Call* call = NULL;
553
554
0
  WINPR_ASSERT(smartcard);
555
0
  WINPR_ASSERT(out);
556
0
  WINPR_ASSERT(operation);
557
558
0
  call = &operation->call.contextAndTwoStringW;
559
0
  ret.ReturnCode =
560
0
      wrap(smartcard, SCardAddReaderToGroupW, operation->hContext, call->sz1, call->sz2);
561
0
  scard_log_status_error(TAG, "SCardAddReaderToGroupW", ret.ReturnCode);
562
0
  smartcard_trace_long_return(&ret, "SCardAddReaderToGroupA");
563
0
  return ret.ReturnCode;
564
0
}
565
566
static LONG smartcard_RemoveReaderFromGroupA_Call(scard_call_context* smartcard, wStream* out,
567
                                                  SMARTCARD_OPERATION* operation)
568
0
{
569
0
  Long_Return ret = { 0 };
570
0
  ContextAndTwoStringA_Call* call = NULL;
571
572
0
  WINPR_ASSERT(smartcard);
573
0
  WINPR_ASSERT(out);
574
0
  WINPR_ASSERT(operation);
575
576
0
  call = &operation->call.contextAndTwoStringA;
577
0
  ret.ReturnCode =
578
0
      wrap(smartcard, SCardRemoveReaderFromGroupA, operation->hContext, call->sz1, call->sz2);
579
0
  scard_log_status_error(TAG, "SCardRemoveReaderFromGroupA", ret.ReturnCode);
580
0
  smartcard_trace_long_return(&ret, "SCardRemoveReaderFromGroupA");
581
0
  return ret.ReturnCode;
582
0
}
583
584
static LONG smartcard_RemoveReaderFromGroupW_Call(scard_call_context* smartcard, wStream* out,
585
                                                  SMARTCARD_OPERATION* operation)
586
0
{
587
0
  Long_Return ret = { 0 };
588
0
  ContextAndTwoStringW_Call* call = NULL;
589
590
0
  WINPR_ASSERT(smartcard);
591
0
  WINPR_ASSERT(out);
592
0
  WINPR_ASSERT(operation);
593
594
0
  call = &operation->call.contextAndTwoStringW;
595
0
  ret.ReturnCode =
596
0
      wrap(smartcard, SCardRemoveReaderFromGroupW, operation->hContext, call->sz1, call->sz2);
597
0
  scard_log_status_error(TAG, "SCardRemoveReaderFromGroupW", ret.ReturnCode);
598
0
  smartcard_trace_long_return(&ret, "SCardRemoveReaderFromGroupW");
599
0
  return ret.ReturnCode;
600
0
}
601
602
static LONG smartcard_LocateCardsA_Call(scard_call_context* smartcard, wStream* out,
603
                                        SMARTCARD_OPERATION* operation)
604
0
{
605
0
  LONG status = 0;
606
0
  LocateCards_Return ret = { 0 };
607
0
  LocateCardsA_Call* call = NULL;
608
609
0
  WINPR_ASSERT(smartcard);
610
0
  WINPR_ASSERT(operation);
611
612
0
  call = &operation->call.locateCardsA;
613
614
0
  ret.ReturnCode = wrap(smartcard, SCardLocateCardsA, operation->hContext, call->mszCards,
615
0
                        call->rgReaderStates, call->cReaders);
616
0
  scard_log_status_error(TAG, "SCardLocateCardsA", ret.ReturnCode);
617
0
  ret.cReaders = call->cReaders;
618
0
  ret.rgReaderStates = NULL;
619
620
0
  if (ret.cReaders > 0)
621
0
  {
622
0
    ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return));
623
624
0
    if (!ret.rgReaderStates)
625
0
      return STATUS_NO_MEMORY;
626
0
  }
627
628
0
  for (UINT32 x = 0; x < ret.cReaders; x++)
629
0
  {
630
0
    ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
631
0
    ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
632
0
    ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
633
0
    CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
634
0
               sizeof(ret.rgReaderStates[x].rgbAtr));
635
0
  }
636
637
0
  status = smartcard_pack_locate_cards_return(out, &ret);
638
639
0
  if (status != SCARD_S_SUCCESS)
640
0
    return status;
641
642
0
  return ret.ReturnCode;
643
0
}
644
645
static LONG smartcard_LocateCardsW_Call(scard_call_context* smartcard, wStream* out,
646
                                        SMARTCARD_OPERATION* operation)
647
0
{
648
0
  LONG status = 0;
649
0
  LocateCards_Return ret = { 0 };
650
0
  LocateCardsW_Call* call = NULL;
651
652
0
  WINPR_ASSERT(smartcard);
653
0
  WINPR_ASSERT(operation);
654
655
0
  call = &operation->call.locateCardsW;
656
657
0
  ret.ReturnCode = wrap(smartcard, SCardLocateCardsW, operation->hContext, call->mszCards,
658
0
                        call->rgReaderStates, call->cReaders);
659
0
  scard_log_status_error(TAG, "SCardLocateCardsW", ret.ReturnCode);
660
0
  ret.cReaders = call->cReaders;
661
0
  ret.rgReaderStates = NULL;
662
663
0
  if (ret.cReaders > 0)
664
0
  {
665
0
    ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return));
666
667
0
    if (!ret.rgReaderStates)
668
0
      return STATUS_NO_MEMORY;
669
0
  }
670
671
0
  for (UINT32 x = 0; x < ret.cReaders; x++)
672
0
  {
673
0
    ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
674
0
    ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
675
0
    ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
676
0
    CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
677
0
               sizeof(ret.rgReaderStates[x].rgbAtr));
678
0
  }
679
680
0
  status = smartcard_pack_locate_cards_return(out, &ret);
681
682
0
  if (status != SCARD_S_SUCCESS)
683
0
    return status;
684
685
0
  return ret.ReturnCode;
686
0
}
687
688
static LONG smartcard_ReadCacheA_Call(scard_call_context* smartcard, wStream* out,
689
                                      SMARTCARD_OPERATION* operation)
690
0
{
691
0
  LONG status = 0;
692
0
  BOOL autoalloc = 0;
693
0
  ReadCache_Return ret = { 0 };
694
0
  ReadCacheA_Call* call = NULL;
695
696
0
  WINPR_ASSERT(smartcard);
697
0
  WINPR_ASSERT(out);
698
0
  WINPR_ASSERT(operation);
699
700
0
  call = &operation->call.readCacheA;
701
0
  autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE);
702
703
0
  if (!call->Common.fPbDataIsNULL)
704
0
  {
705
0
    ret.cbDataLen = call->Common.cbDataLen;
706
0
    if (!autoalloc)
707
0
    {
708
0
      ret.pbData = malloc(ret.cbDataLen);
709
0
      if (!ret.pbData)
710
0
        return SCARD_F_INTERNAL_ERROR;
711
0
    }
712
0
  }
713
714
0
  if (autoalloc)
715
0
    ret.ReturnCode = wrap(smartcard, SCardReadCacheA, operation->hContext,
716
0
                          call->Common.CardIdentifier, call->Common.FreshnessCounter,
717
0
                          call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
718
0
  else
719
0
    ret.ReturnCode =
720
0
        wrap(smartcard, SCardReadCacheA, operation->hContext, call->Common.CardIdentifier,
721
0
             call->Common.FreshnessCounter, call->szLookupName, ret.pbData, &ret.cbDataLen);
722
0
  if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
723
0
      (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
724
0
  {
725
0
    scard_log_status_error(TAG, "SCardReadCacheA", ret.ReturnCode);
726
0
  }
727
728
0
  status = smartcard_pack_read_cache_return(out, &ret);
729
0
  if (autoalloc)
730
0
    wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
731
0
  else
732
0
    free(ret.pbData);
733
0
  if (status != SCARD_S_SUCCESS)
734
0
    return status;
735
736
0
  return ret.ReturnCode;
737
0
}
738
739
static LONG smartcard_ReadCacheW_Call(scard_call_context* smartcard, wStream* out,
740
                                      SMARTCARD_OPERATION* operation)
741
0
{
742
0
  LONG status = 0;
743
0
  ReadCache_Return ret = { 0 };
744
0
  ReadCacheW_Call* call = NULL;
745
746
0
  WINPR_ASSERT(smartcard);
747
0
  WINPR_ASSERT(out);
748
0
  WINPR_ASSERT(operation);
749
750
0
  call = &operation->call.readCacheW;
751
752
0
  if (!call->Common.fPbDataIsNULL)
753
0
    ret.cbDataLen = SCARD_AUTOALLOCATE;
754
755
0
  ret.ReturnCode =
756
0
      wrap(smartcard, SCardReadCacheW, operation->hContext, call->Common.CardIdentifier,
757
0
           call->Common.FreshnessCounter, call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
758
759
0
  if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
760
0
      (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
761
0
  {
762
0
    scard_log_status_error(TAG, "SCardReadCacheW", ret.ReturnCode);
763
0
  }
764
765
0
  status = smartcard_pack_read_cache_return(out, &ret);
766
767
0
  wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
768
769
0
  if (status != SCARD_S_SUCCESS)
770
0
    return status;
771
772
0
  return ret.ReturnCode;
773
0
}
774
775
static LONG smartcard_WriteCacheA_Call(scard_call_context* smartcard, wStream* out,
776
                                       SMARTCARD_OPERATION* operation)
777
0
{
778
0
  Long_Return ret = { 0 };
779
0
  WriteCacheA_Call* call = NULL;
780
781
0
  WINPR_ASSERT(smartcard);
782
0
  WINPR_ASSERT(out);
783
0
  WINPR_ASSERT(operation);
784
785
0
  call = &operation->call.writeCacheA;
786
787
0
  ret.ReturnCode = wrap(smartcard, SCardWriteCacheA, operation->hContext,
788
0
                        call->Common.CardIdentifier, call->Common.FreshnessCounter,
789
0
                        call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
790
0
  scard_log_status_error(TAG, "SCardWriteCacheA", ret.ReturnCode);
791
0
  smartcard_trace_long_return(&ret, "SCardWriteCacheA");
792
0
  return ret.ReturnCode;
793
0
}
794
795
static LONG smartcard_WriteCacheW_Call(scard_call_context* smartcard, wStream* out,
796
                                       SMARTCARD_OPERATION* operation)
797
0
{
798
0
  Long_Return ret = { 0 };
799
0
  WriteCacheW_Call* call = NULL;
800
801
0
  WINPR_ASSERT(smartcard);
802
0
  WINPR_ASSERT(out);
803
0
  WINPR_ASSERT(operation);
804
805
0
  call = &operation->call.writeCacheW;
806
807
0
  ret.ReturnCode = wrap(smartcard, SCardWriteCacheW, operation->hContext,
808
0
                        call->Common.CardIdentifier, call->Common.FreshnessCounter,
809
0
                        call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
810
0
  scard_log_status_error(TAG, "SCardWriteCacheW", ret.ReturnCode);
811
0
  smartcard_trace_long_return(&ret, "SCardWriteCacheW");
812
0
  return ret.ReturnCode;
813
0
}
814
815
static LONG smartcard_GetTransmitCount_Call(scard_call_context* smartcard, wStream* out,
816
                                            SMARTCARD_OPERATION* operation)
817
0
{
818
0
  LONG status = 0;
819
0
  GetTransmitCount_Return ret = { 0 };
820
821
0
  WINPR_ASSERT(smartcard);
822
0
  WINPR_ASSERT(out);
823
0
  WINPR_ASSERT(operation);
824
825
0
  ret.ReturnCode = wrap(smartcard, SCardGetTransmitCount, operation->hCard, &ret.cTransmitCount);
826
0
  scard_log_status_error(TAG, "SCardGetTransmitCount", ret.ReturnCode);
827
0
  status = smartcard_pack_get_transmit_count_return(out, &ret);
828
0
  if (status != SCARD_S_SUCCESS)
829
0
    return status;
830
831
0
  return ret.ReturnCode;
832
0
}
833
834
static LONG smartcard_ReleaseStartedEvent_Call(scard_call_context* smartcard, wStream* out,
835
                                               SMARTCARD_OPERATION* operation)
836
0
{
837
0
  WINPR_UNUSED(smartcard);
838
0
  WINPR_UNUSED(out);
839
0
  WINPR_UNUSED(operation);
840
841
0
  WLog_WARN(TAG, "According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
842
0
                 "this is not supported?!?");
843
0
  return SCARD_E_UNSUPPORTED_FEATURE;
844
0
}
845
846
static LONG smartcard_GetReaderIcon_Call(scard_call_context* smartcard, wStream* out,
847
                                         SMARTCARD_OPERATION* operation)
848
0
{
849
0
  LONG status = 0;
850
0
  GetReaderIcon_Return ret = { 0 };
851
0
  GetReaderIcon_Call* call = NULL;
852
853
0
  WINPR_ASSERT(smartcard);
854
0
  WINPR_ASSERT(out);
855
0
  WINPR_ASSERT(operation);
856
857
0
  call = &operation->call.getReaderIcon;
858
859
0
  ret.cbDataLen = SCARD_AUTOALLOCATE;
860
0
  ret.ReturnCode = wrap(smartcard, SCardGetReaderIconW, operation->hContext, call->szReaderName,
861
0
                        (LPBYTE)&ret.pbData, &ret.cbDataLen);
862
0
  scard_log_status_error(TAG, "SCardGetReaderIconW", ret.ReturnCode);
863
0
  if (ret.cbDataLen == SCARD_AUTOALLOCATE)
864
0
    return SCARD_F_UNKNOWN_ERROR;
865
866
0
  status = smartcard_pack_get_reader_icon_return(out, &ret);
867
0
  wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
868
0
  if (status != SCARD_S_SUCCESS)
869
0
    return status;
870
871
0
  return ret.ReturnCode;
872
0
}
873
874
static LONG smartcard_GetDeviceTypeId_Call(scard_call_context* smartcard, wStream* out,
875
                                           SMARTCARD_OPERATION* operation)
876
0
{
877
0
  LONG status = 0;
878
0
  GetDeviceTypeId_Return ret = { 0 };
879
0
  GetDeviceTypeId_Call* call = NULL;
880
881
0
  WINPR_ASSERT(smartcard);
882
0
  WINPR_ASSERT(out);
883
0
  WINPR_ASSERT(operation);
884
885
0
  call = &operation->call.getDeviceTypeId;
886
887
0
  ret.ReturnCode = wrap(smartcard, SCardGetDeviceTypeIdW, operation->hContext, call->szReaderName,
888
0
                        &ret.dwDeviceId);
889
0
  scard_log_status_error(TAG, "SCardGetDeviceTypeIdW", ret.ReturnCode);
890
891
0
  status = smartcard_pack_device_type_id_return(out, &ret);
892
0
  if (status != SCARD_S_SUCCESS)
893
0
    return status;
894
895
0
  return ret.ReturnCode;
896
0
}
897
898
static LONG smartcard_GetStatusChangeA_Call(scard_call_context* smartcard, wStream* out,
899
                                            SMARTCARD_OPERATION* operation)
900
0
{
901
0
  LONG status = STATUS_NO_MEMORY;
902
0
  DWORD dwTimeOut = 0;
903
0
  const DWORD dwTimeStep = 100;
904
0
  GetStatusChange_Return ret = { 0 };
905
0
  GetStatusChangeA_Call* call = NULL;
906
0
  LPSCARD_READERSTATEA rgReaderStates = NULL;
907
908
0
  WINPR_ASSERT(smartcard);
909
0
  WINPR_ASSERT(out);
910
0
  WINPR_ASSERT(operation);
911
912
0
  call = &operation->call.getStatusChangeA;
913
0
  dwTimeOut = call->dwTimeOut;
914
915
0
  if (call->cReaders > 0)
916
0
  {
917
0
    ret.cReaders = call->cReaders;
918
0
    rgReaderStates = calloc(ret.cReaders, sizeof(SCARD_READERSTATEA));
919
0
    ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return));
920
0
    if (!rgReaderStates || !ret.rgReaderStates)
921
0
      goto fail;
922
0
  }
923
924
0
  for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
925
0
  {
926
0
    if (call->cReaders > 0)
927
0
      memcpy(rgReaderStates, call->rgReaderStates,
928
0
             call->cReaders * sizeof(SCARD_READERSTATEA));
929
0
    ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
930
0
                          MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
931
0
    if (ret.ReturnCode != SCARD_E_TIMEOUT)
932
0
      break;
933
0
    if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
934
0
      break;
935
0
    if (dwTimeOut != INFINITE)
936
0
      x += dwTimeStep;
937
0
  }
938
0
  scard_log_status_error(TAG, "SCardGetStatusChangeA", ret.ReturnCode);
939
940
0
  for (UINT32 index = 0; index < ret.cReaders; index++)
941
0
  {
942
0
    const SCARD_READERSTATEA* cur = &rgReaderStates[index];
943
0
    ReaderState_Return* rout = &ret.rgReaderStates[index];
944
945
0
    rout->dwCurrentState = cur->dwCurrentState;
946
0
    rout->dwEventState = cur->dwEventState;
947
0
    rout->cbAtr = cur->cbAtr;
948
0
    CopyMemory(&(rout->rgbAtr), cur->rgbAtr, sizeof(rout->rgbAtr));
949
0
  }
950
951
0
  status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
952
0
fail:
953
0
  free(ret.rgReaderStates);
954
0
  free(rgReaderStates);
955
0
  if (status != SCARD_S_SUCCESS)
956
0
    return status;
957
0
  return ret.ReturnCode;
958
0
}
959
960
static LONG smartcard_GetStatusChangeW_Call(scard_call_context* smartcard, wStream* out,
961
                                            SMARTCARD_OPERATION* operation)
962
0
{
963
0
  LONG status = STATUS_NO_MEMORY;
964
0
  DWORD dwTimeOut = 0;
965
0
  const DWORD dwTimeStep = 100;
966
0
  GetStatusChange_Return ret = { 0 };
967
0
  GetStatusChangeW_Call* call = NULL;
968
0
  LPSCARD_READERSTATEW rgReaderStates = NULL;
969
970
0
  WINPR_ASSERT(smartcard);
971
0
  WINPR_ASSERT(out);
972
0
  WINPR_ASSERT(operation);
973
974
0
  call = &operation->call.getStatusChangeW;
975
0
  dwTimeOut = call->dwTimeOut;
976
977
0
  if (call->cReaders > 0)
978
0
  {
979
0
    ret.cReaders = call->cReaders;
980
0
    rgReaderStates = calloc(ret.cReaders, sizeof(SCARD_READERSTATEW));
981
0
    ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return));
982
0
    if (!rgReaderStates || !ret.rgReaderStates)
983
0
      goto fail;
984
0
  }
985
986
0
  for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
987
0
  {
988
0
    if (call->cReaders > 0)
989
0
      memcpy(rgReaderStates, call->rgReaderStates,
990
0
             call->cReaders * sizeof(SCARD_READERSTATEW));
991
0
    {
992
0
      ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
993
0
                            MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
994
0
    }
995
0
    if (ret.ReturnCode != SCARD_E_TIMEOUT)
996
0
      break;
997
0
    if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
998
0
      break;
999
0
    if (dwTimeOut != INFINITE)
1000
0
      x += dwTimeStep;
1001
0
  }
1002
0
  scard_log_status_error(TAG, "SCardGetStatusChangeW", ret.ReturnCode);
1003
1004
0
  for (UINT32 index = 0; index < ret.cReaders; index++)
1005
0
  {
1006
0
    const SCARD_READERSTATEW* cur = &rgReaderStates[index];
1007
0
    ReaderState_Return* rout = &ret.rgReaderStates[index];
1008
1009
0
    rout->dwCurrentState = cur->dwCurrentState;
1010
0
    rout->dwEventState = cur->dwEventState;
1011
0
    rout->cbAtr = cur->cbAtr;
1012
0
    CopyMemory(&(rout->rgbAtr), cur->rgbAtr, sizeof(rout->rgbAtr));
1013
0
  }
1014
1015
0
  status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
1016
0
fail:
1017
0
  free(ret.rgReaderStates);
1018
0
  free(rgReaderStates);
1019
0
  if (status != SCARD_S_SUCCESS)
1020
0
    return status;
1021
0
  return ret.ReturnCode;
1022
0
}
1023
1024
static LONG smartcard_Cancel_Call(scard_call_context* smartcard, wStream* out,
1025
                                  SMARTCARD_OPERATION* operation)
1026
0
{
1027
0
  Long_Return ret = { 0 };
1028
1029
0
  WINPR_ASSERT(smartcard);
1030
0
  WINPR_ASSERT(out);
1031
0
  WINPR_ASSERT(operation);
1032
1033
0
  ret.ReturnCode = wrap(smartcard, SCardCancel, operation->hContext);
1034
0
  scard_log_status_error(TAG, "SCardCancel", ret.ReturnCode);
1035
0
  smartcard_trace_long_return(&ret, "Cancel");
1036
0
  return ret.ReturnCode;
1037
0
}
1038
1039
static LONG smartcard_ConnectA_Call(scard_call_context* smartcard, wStream* out,
1040
                                    SMARTCARD_OPERATION* operation)
1041
0
{
1042
0
  LONG status = 0;
1043
0
  SCARDHANDLE hCard = 0;
1044
0
  Connect_Return ret = { 0 };
1045
0
  ConnectA_Call* call = NULL;
1046
1047
0
  WINPR_ASSERT(smartcard);
1048
0
  WINPR_ASSERT(out);
1049
0
  WINPR_ASSERT(operation);
1050
1051
0
  call = &operation->call.connectA;
1052
1053
0
  if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1054
0
      (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1055
0
  {
1056
0
    call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1057
0
  }
1058
1059
0
  ret.ReturnCode = wrap(smartcard, SCardConnectA, operation->hContext, (char*)call->szReader,
1060
0
                        call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1061
0
                        &ret.dwActiveProtocol);
1062
0
  smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1063
0
  smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1064
1065
0
  status = smartcard_pack_connect_return(out, &ret);
1066
0
  if (status != SCARD_S_SUCCESS)
1067
0
    goto out_fail;
1068
1069
0
  status = ret.ReturnCode;
1070
0
out_fail:
1071
1072
0
  return status;
1073
0
}
1074
1075
static LONG smartcard_ConnectW_Call(scard_call_context* smartcard, wStream* out,
1076
                                    SMARTCARD_OPERATION* operation)
1077
0
{
1078
0
  LONG status = 0;
1079
0
  SCARDHANDLE hCard = 0;
1080
0
  Connect_Return ret = { 0 };
1081
0
  ConnectW_Call* call = NULL;
1082
1083
0
  WINPR_ASSERT(smartcard);
1084
0
  WINPR_ASSERT(out);
1085
0
  WINPR_ASSERT(operation);
1086
1087
0
  call = &operation->call.connectW;
1088
1089
0
  if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1090
0
      (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1091
0
  {
1092
0
    call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1093
0
  }
1094
1095
0
  ret.ReturnCode = wrap(smartcard, SCardConnectW, operation->hContext, (WCHAR*)call->szReader,
1096
0
                        call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1097
0
                        &ret.dwActiveProtocol);
1098
0
  smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1099
0
  smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1100
1101
0
  status = smartcard_pack_connect_return(out, &ret);
1102
0
  if (status != SCARD_S_SUCCESS)
1103
0
    goto out_fail;
1104
1105
0
  status = ret.ReturnCode;
1106
0
out_fail:
1107
1108
0
  return status;
1109
0
}
1110
1111
static LONG smartcard_Reconnect_Call(scard_call_context* smartcard, wStream* out,
1112
                                     SMARTCARD_OPERATION* operation)
1113
0
{
1114
0
  LONG status = 0;
1115
0
  Reconnect_Return ret = { 0 };
1116
0
  Reconnect_Call* call = NULL;
1117
1118
0
  WINPR_ASSERT(smartcard);
1119
0
  WINPR_ASSERT(out);
1120
0
  WINPR_ASSERT(operation);
1121
1122
0
  call = &operation->call.reconnect;
1123
0
  ret.ReturnCode =
1124
0
      wrap(smartcard, SCardReconnect, operation->hCard, call->dwShareMode,
1125
0
           call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
1126
0
  scard_log_status_error(TAG, "SCardReconnect", ret.ReturnCode);
1127
0
  status = smartcard_pack_reconnect_return(out, &ret);
1128
0
  if (status != SCARD_S_SUCCESS)
1129
0
    return status;
1130
1131
0
  return ret.ReturnCode;
1132
0
}
1133
1134
static LONG smartcard_Disconnect_Call(scard_call_context* smartcard, wStream* out,
1135
                                      SMARTCARD_OPERATION* operation)
1136
0
{
1137
0
  Long_Return ret = { 0 };
1138
0
  HCardAndDisposition_Call* call = NULL;
1139
1140
0
  WINPR_ASSERT(smartcard);
1141
0
  WINPR_ASSERT(out);
1142
0
  WINPR_ASSERT(operation);
1143
1144
0
  call = &operation->call.hCardAndDisposition;
1145
1146
0
  ret.ReturnCode = wrap(smartcard, SCardDisconnect, operation->hCard, call->dwDisposition);
1147
0
  scard_log_status_error(TAG, "SCardDisconnect", ret.ReturnCode);
1148
0
  smartcard_trace_long_return(&ret, "Disconnect");
1149
1150
0
  return ret.ReturnCode;
1151
0
}
1152
1153
static LONG smartcard_BeginTransaction_Call(scard_call_context* smartcard, wStream* out,
1154
                                            SMARTCARD_OPERATION* operation)
1155
0
{
1156
0
  Long_Return ret = { 0 };
1157
1158
0
  WINPR_ASSERT(smartcard);
1159
0
  WINPR_ASSERT(out);
1160
0
  WINPR_ASSERT(operation);
1161
1162
0
  ret.ReturnCode = wrap(smartcard, SCardBeginTransaction, operation->hCard);
1163
0
  scard_log_status_error(TAG, "SCardBeginTransaction", ret.ReturnCode);
1164
0
  smartcard_trace_long_return(&ret, "BeginTransaction");
1165
0
  return ret.ReturnCode;
1166
0
}
1167
1168
static LONG smartcard_EndTransaction_Call(scard_call_context* smartcard, wStream* out,
1169
                                          SMARTCARD_OPERATION* operation)
1170
0
{
1171
0
  Long_Return ret = { 0 };
1172
0
  HCardAndDisposition_Call* call = NULL;
1173
1174
0
  WINPR_ASSERT(smartcard);
1175
0
  WINPR_ASSERT(out);
1176
0
  WINPR_ASSERT(operation);
1177
1178
0
  call = &operation->call.hCardAndDisposition;
1179
1180
0
  ret.ReturnCode = wrap(smartcard, SCardEndTransaction, operation->hCard, call->dwDisposition);
1181
0
  scard_log_status_error(TAG, "SCardEndTransaction", ret.ReturnCode);
1182
0
  smartcard_trace_long_return(&ret, "EndTransaction");
1183
0
  return ret.ReturnCode;
1184
0
}
1185
1186
static LONG smartcard_State_Call(scard_call_context* smartcard, wStream* out,
1187
                                 SMARTCARD_OPERATION* operation)
1188
0
{
1189
0
  LONG status = 0;
1190
0
  State_Return ret = { 0 };
1191
1192
0
  WINPR_ASSERT(smartcard);
1193
0
  WINPR_ASSERT(out);
1194
0
  WINPR_ASSERT(operation);
1195
1196
0
  ret.cbAtrLen = SCARD_ATR_LENGTH;
1197
0
  ret.ReturnCode = wrap(smartcard, SCardState, operation->hCard, &ret.dwState, &ret.dwProtocol,
1198
0
                        (BYTE*)&ret.rgAtr, &ret.cbAtrLen);
1199
1200
0
  scard_log_status_error(TAG, "SCardState", ret.ReturnCode);
1201
0
  status = smartcard_pack_state_return(out, &ret);
1202
0
  if (status != SCARD_S_SUCCESS)
1203
0
    return status;
1204
1205
0
  return ret.ReturnCode;
1206
0
}
1207
1208
static LONG smartcard_StatusA_Call(scard_call_context* smartcard, wStream* out,
1209
                                   SMARTCARD_OPERATION* operation)
1210
0
{
1211
0
  LONG status = 0;
1212
0
  Status_Return ret = { 0 };
1213
0
  DWORD cchReaderLen = 0;
1214
0
  DWORD cbAtrLen = 0;
1215
0
  LPSTR mszReaderNames = NULL;
1216
0
  Status_Call* call = NULL;
1217
1218
0
  WINPR_ASSERT(smartcard);
1219
0
  WINPR_ASSERT(out);
1220
0
  WINPR_ASSERT(operation);
1221
1222
0
  call = &operation->call.status;
1223
1224
0
  call->cbAtrLen = 32;
1225
0
  cbAtrLen = call->cbAtrLen;
1226
1227
0
  if (call->fmszReaderNamesIsNULL)
1228
0
    cchReaderLen = 0;
1229
0
  else
1230
0
    cchReaderLen = SCARD_AUTOALLOCATE;
1231
1232
0
  status = ret.ReturnCode =
1233
0
      wrap(smartcard, SCardStatusA, operation->hCard,
1234
0
           call->fmszReaderNamesIsNULL ? NULL : (LPSTR)&mszReaderNames, &cchReaderLen,
1235
0
           &ret.dwState, &ret.dwProtocol, cbAtrLen ? (BYTE*)&ret.pbAtr : NULL, &cbAtrLen);
1236
1237
0
  scard_log_status_error(TAG, "SCardStatusA", status);
1238
0
  if (cchReaderLen == SCARD_AUTOALLOCATE)
1239
0
    return SCARD_F_UNKNOWN_ERROR;
1240
1241
0
  if (status == SCARD_S_SUCCESS)
1242
0
  {
1243
0
    if (!call->fmszReaderNamesIsNULL)
1244
0
      ret.mszReaderNames = (BYTE*)mszReaderNames;
1245
1246
0
    ret.cBytes = cchReaderLen;
1247
1248
0
    if (call->cbAtrLen)
1249
0
      ret.cbAtrLen = cbAtrLen;
1250
0
  }
1251
1252
0
  status = smartcard_pack_status_return(out, &ret, FALSE);
1253
1254
0
  if (mszReaderNames)
1255
0
    wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1256
1257
0
  if (status != SCARD_S_SUCCESS)
1258
0
    return status;
1259
0
  return ret.ReturnCode;
1260
0
}
1261
1262
static LONG smartcard_StatusW_Call(scard_call_context* smartcard, wStream* out,
1263
                                   SMARTCARD_OPERATION* operation)
1264
0
{
1265
0
  LONG status = 0;
1266
0
  Status_Return ret = { 0 };
1267
0
  LPWSTR mszReaderNames = NULL;
1268
0
  Status_Call* call = NULL;
1269
0
  DWORD cbAtrLen = 0;
1270
1271
0
  WINPR_ASSERT(smartcard);
1272
0
  WINPR_ASSERT(out);
1273
0
  WINPR_ASSERT(operation);
1274
1275
0
  call = &operation->call.status;
1276
1277
  /**
1278
   * [MS-RDPESC]
1279
   * According to 2.2.2.18 Status_Call cbAtrLen is unused an must be ignored upon receipt.
1280
   */
1281
0
  cbAtrLen = call->cbAtrLen = 32;
1282
1283
0
  if (call->fmszReaderNamesIsNULL)
1284
0
    ret.cBytes = 0;
1285
0
  else
1286
0
    ret.cBytes = SCARD_AUTOALLOCATE;
1287
1288
0
  status = ret.ReturnCode =
1289
0
      wrap(smartcard, SCardStatusW, operation->hCard,
1290
0
           call->fmszReaderNamesIsNULL ? NULL : (LPWSTR)&mszReaderNames, &ret.cBytes,
1291
0
           &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
1292
0
  scard_log_status_error(TAG, "SCardStatusW", status);
1293
0
  if (ret.cBytes == SCARD_AUTOALLOCATE)
1294
0
    return SCARD_F_UNKNOWN_ERROR;
1295
1296
0
  if (status == SCARD_S_SUCCESS)
1297
0
  {
1298
0
    if (!call->fmszReaderNamesIsNULL)
1299
0
      ret.mszReaderNames = (BYTE*)mszReaderNames;
1300
1301
0
    ret.cbAtrLen = cbAtrLen;
1302
0
  }
1303
1304
  /* SCardStatusW returns number of characters, we need number of bytes */
1305
0
  WINPR_ASSERT(ret.cBytes != SCARD_AUTOALLOCATE);
1306
0
  ret.cBytes *= sizeof(WCHAR);
1307
1308
0
  status = smartcard_pack_status_return(out, &ret, TRUE);
1309
0
  if (status != SCARD_S_SUCCESS)
1310
0
    return status;
1311
1312
0
  if (mszReaderNames)
1313
0
    wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1314
1315
0
  return ret.ReturnCode;
1316
0
}
1317
1318
static LONG smartcard_Transmit_Call(scard_call_context* smartcard, wStream* out,
1319
                                    SMARTCARD_OPERATION* operation)
1320
0
{
1321
0
  LONG status = 0;
1322
0
  Transmit_Return ret = { 0 };
1323
0
  Transmit_Call* call = NULL;
1324
1325
0
  WINPR_ASSERT(smartcard);
1326
0
  WINPR_ASSERT(out);
1327
0
  WINPR_ASSERT(operation);
1328
1329
0
  call = &operation->call.transmit;
1330
0
  ret.cbRecvLength = 0;
1331
0
  ret.pbRecvBuffer = NULL;
1332
1333
0
  if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
1334
0
  {
1335
0
    if (call->cbRecvLength >= 66560)
1336
0
      call->cbRecvLength = 66560;
1337
1338
0
    ret.cbRecvLength = call->cbRecvLength;
1339
0
    ret.pbRecvBuffer = (BYTE*)malloc(ret.cbRecvLength);
1340
1341
0
    if (!ret.pbRecvBuffer)
1342
0
      return STATUS_NO_MEMORY;
1343
0
  }
1344
1345
0
  ret.pioRecvPci = call->pioRecvPci;
1346
0
  ret.ReturnCode =
1347
0
      wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
1348
0
           call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
1349
1350
0
  scard_log_status_error(TAG, "SCardTransmit", ret.ReturnCode);
1351
1352
0
  status = smartcard_pack_transmit_return(out, &ret);
1353
0
  free(ret.pbRecvBuffer);
1354
1355
0
  if (status != SCARD_S_SUCCESS)
1356
0
    return status;
1357
0
  return ret.ReturnCode;
1358
0
}
1359
1360
static LONG smartcard_Control_Call(scard_call_context* smartcard, wStream* out,
1361
                                   SMARTCARD_OPERATION* operation)
1362
0
{
1363
0
  LONG status = 0;
1364
0
  Control_Return ret = { 0 };
1365
0
  Control_Call* call = NULL;
1366
1367
0
  WINPR_ASSERT(smartcard);
1368
0
  WINPR_ASSERT(out);
1369
0
  WINPR_ASSERT(operation);
1370
1371
0
  call = &operation->call.control;
1372
0
  ret.cbOutBufferSize = call->cbOutBufferSize;
1373
0
  ret.pvOutBuffer = (BYTE*)malloc(call->cbOutBufferSize);
1374
1375
0
  if (!ret.pvOutBuffer)
1376
0
    return SCARD_E_NO_MEMORY;
1377
1378
0
  ret.ReturnCode =
1379
0
      wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
1380
0
           call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
1381
0
  scard_log_status_error(TAG, "SCardControl", ret.ReturnCode);
1382
0
  status = smartcard_pack_control_return(out, &ret);
1383
1384
0
  free(ret.pvOutBuffer);
1385
0
  if (status != SCARD_S_SUCCESS)
1386
0
    return status;
1387
0
  return ret.ReturnCode;
1388
0
}
1389
1390
static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard, wStream* out,
1391
                                     SMARTCARD_OPERATION* operation)
1392
0
{
1393
0
  BOOL autoAllocate = FALSE;
1394
0
  LONG status = 0;
1395
0
  DWORD cbAttrLen = 0;
1396
0
  LPBYTE pbAttr = NULL;
1397
0
  GetAttrib_Return ret = { 0 };
1398
0
  const GetAttrib_Call* call = NULL;
1399
1400
0
  WINPR_ASSERT(smartcard);
1401
0
  WINPR_ASSERT(operation);
1402
1403
0
  call = &operation->call.getAttrib;
1404
1405
0
  if (!call->fpbAttrIsNULL)
1406
0
  {
1407
0
    autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE) ? TRUE : FALSE;
1408
0
    cbAttrLen = call->cbAttrLen;
1409
0
    if (cbAttrLen && !autoAllocate)
1410
0
    {
1411
0
      ret.pbAttr = (BYTE*)malloc(cbAttrLen);
1412
1413
0
      if (!ret.pbAttr)
1414
0
        return SCARD_E_NO_MEMORY;
1415
0
    }
1416
1417
0
    pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
1418
0
  }
1419
1420
0
  ret.ReturnCode =
1421
0
      wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
1422
0
  scard_log_status_error(TAG, "SCardGetAttrib", ret.ReturnCode);
1423
0
  if (cbAttrLen == SCARD_AUTOALLOCATE)
1424
0
    return SCARD_F_UNKNOWN_ERROR;
1425
1426
0
  ret.cbAttrLen = cbAttrLen;
1427
1428
0
  status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
1429
1430
0
  if (autoAllocate)
1431
0
    wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
1432
0
  else
1433
0
    free(ret.pbAttr);
1434
0
  return status;
1435
0
}
1436
1437
static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard, wStream* out,
1438
                                     SMARTCARD_OPERATION* operation)
1439
0
{
1440
0
  Long_Return ret = { 0 };
1441
0
  SetAttrib_Call* call = NULL;
1442
1443
0
  WINPR_ASSERT(smartcard);
1444
0
  WINPR_ASSERT(out);
1445
0
  WINPR_ASSERT(operation);
1446
1447
0
  call = &operation->call.setAttrib;
1448
1449
0
  ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
1450
0
                        call->cbAttrLen);
1451
0
  scard_log_status_error(TAG, "SCardSetAttrib", ret.ReturnCode);
1452
0
  smartcard_trace_long_return(&ret, "SetAttrib");
1453
1454
0
  return ret.ReturnCode;
1455
0
}
1456
1457
static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard, wStream* out,
1458
                                              SMARTCARD_OPERATION* operation)
1459
0
{
1460
0
  LONG status = SCARD_S_SUCCESS;
1461
1462
0
  WINPR_ASSERT(smartcard);
1463
0
  WINPR_ASSERT(out);
1464
0
  WINPR_UNUSED(operation);
1465
1466
0
  if (!smartcard->StartedEvent)
1467
0
    smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
1468
1469
0
  if (!smartcard->StartedEvent)
1470
0
    status = SCARD_E_NO_SERVICE;
1471
1472
0
  return status;
1473
0
}
1474
1475
static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard, wStream* out,
1476
                                             SMARTCARD_OPERATION* operation)
1477
0
{
1478
0
  LONG status = 0;
1479
0
  GetStatusChange_Return ret = { 0 };
1480
0
  LPSCARD_READERSTATEA state = NULL;
1481
0
  LPSCARD_READERSTATEA states = NULL;
1482
0
  LocateCardsByATRA_Call* call = NULL;
1483
1484
0
  WINPR_ASSERT(smartcard);
1485
0
  WINPR_ASSERT(operation);
1486
1487
0
  call = &operation->call.locateCardsByATRA;
1488
0
  states = (LPSCARD_READERSTATEA)calloc(call->cReaders, sizeof(SCARD_READERSTATEA));
1489
1490
0
  if (!states)
1491
0
    return STATUS_NO_MEMORY;
1492
1493
0
  for (UINT32 i = 0; i < call->cReaders; i++)
1494
0
  {
1495
0
    states[i].szReader = call->rgReaderStates[i].szReader;
1496
0
    states[i].dwCurrentState = call->rgReaderStates[i].dwCurrentState;
1497
0
    states[i].dwEventState = call->rgReaderStates[i].dwEventState;
1498
0
    states[i].cbAtr = call->rgReaderStates[i].cbAtr;
1499
0
    CopyMemory(&(states[i].rgbAtr), &(call->rgReaderStates[i].rgbAtr), 36);
1500
0
  }
1501
1502
0
  status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1503
0
                                 0x000001F4, states, call->cReaders);
1504
1505
0
  scard_log_status_error(TAG, "SCardGetStatusChangeA", status);
1506
0
  for (UINT32 i = 0; i < call->cAtrs; i++)
1507
0
  {
1508
0
    for (UINT32 j = 0; j < call->cReaders; j++)
1509
0
    {
1510
0
      for (UINT32 k = 0; k < call->rgAtrMasks[i].cbAtr; k++)
1511
0
      {
1512
0
        if ((call->rgAtrMasks[i].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]) !=
1513
0
            (states[j].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]))
1514
0
        {
1515
0
          break;
1516
0
        }
1517
1518
0
        states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1519
0
      }
1520
0
    }
1521
0
  }
1522
1523
0
  ret.cReaders = call->cReaders;
1524
0
  ret.rgReaderStates = NULL;
1525
1526
0
  if (ret.cReaders > 0)
1527
0
    ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return));
1528
1529
0
  if (!ret.rgReaderStates)
1530
0
  {
1531
0
    free(states);
1532
0
    return STATUS_NO_MEMORY;
1533
0
  }
1534
1535
0
  for (UINT32 i = 0; i < ret.cReaders; i++)
1536
0
  {
1537
0
    state = &states[i];
1538
0
    ret.rgReaderStates[i].dwCurrentState = state->dwCurrentState;
1539
0
    ret.rgReaderStates[i].dwEventState = state->dwEventState;
1540
0
    ret.rgReaderStates[i].cbAtr = state->cbAtr;
1541
0
    CopyMemory(&(ret.rgReaderStates[i].rgbAtr), &(state->rgbAtr),
1542
0
               sizeof(ret.rgReaderStates[i].rgbAtr));
1543
0
  }
1544
1545
0
  free(states);
1546
1547
0
  status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1548
1549
0
  free(ret.rgReaderStates);
1550
0
  if (status != SCARD_S_SUCCESS)
1551
0
    return status;
1552
0
  return ret.ReturnCode;
1553
0
}
1554
1555
LONG smartcard_irp_device_control_call(scard_call_context* smartcard, wStream* out,
1556
                                       UINT32* pIoStatus, SMARTCARD_OPERATION* operation)
1557
0
{
1558
0
  LONG result = 0;
1559
0
  UINT32 offset = 0;
1560
0
  UINT32 ioControlCode = 0;
1561
0
  size_t outputBufferLength = 0;
1562
0
  size_t objectBufferLength = 0;
1563
1564
0
  WINPR_ASSERT(smartcard);
1565
0
  WINPR_ASSERT(out);
1566
0
  WINPR_ASSERT(pIoStatus);
1567
0
  WINPR_ASSERT(operation);
1568
1569
0
  ioControlCode = operation->ioControlCode;
1570
  /**
1571
   * [MS-RDPESC] 3.2.5.1: Sending Outgoing Messages:
1572
   * the output buffer length SHOULD be set to 2048
1573
   *
1574
   * Since it's a SHOULD and not a MUST, we don't care
1575
   * about it, but we still reserve at least 2048 bytes.
1576
   */
1577
0
  if (!Stream_EnsureRemainingCapacity(out, 2048))
1578
0
    return SCARD_E_NO_MEMORY;
1579
1580
  /* Device Control Response */
1581
0
  Stream_Write_UINT32(out, 0);                            /* OutputBufferLength (4 bytes) */
1582
0
  Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH);  /* CommonTypeHeader (8 bytes) */
1583
0
  Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH); /* PrivateTypeHeader (8 bytes) */
1584
0
  Stream_Write_UINT32(out, 0);                            /* Result (4 bytes) */
1585
1586
  /* Call */
1587
0
  switch (ioControlCode)
1588
0
  {
1589
0
    case SCARD_IOCTL_ESTABLISHCONTEXT:
1590
0
      result = smartcard_EstablishContext_Call(smartcard, out, operation);
1591
0
      break;
1592
1593
0
    case SCARD_IOCTL_RELEASECONTEXT:
1594
0
      result = smartcard_ReleaseContext_Call(smartcard, out, operation);
1595
0
      break;
1596
1597
0
    case SCARD_IOCTL_ISVALIDCONTEXT:
1598
0
      result = smartcard_IsValidContext_Call(smartcard, out, operation);
1599
0
      break;
1600
1601
0
    case SCARD_IOCTL_LISTREADERGROUPSA:
1602
0
      result = smartcard_ListReaderGroupsA_Call(smartcard, out, operation);
1603
0
      break;
1604
1605
0
    case SCARD_IOCTL_LISTREADERGROUPSW:
1606
0
      result = smartcard_ListReaderGroupsW_Call(smartcard, out, operation);
1607
0
      break;
1608
1609
0
    case SCARD_IOCTL_LISTREADERSA:
1610
0
      result = smartcard_ListReadersA_Call(smartcard, out, operation);
1611
0
      break;
1612
1613
0
    case SCARD_IOCTL_LISTREADERSW:
1614
0
      result = smartcard_ListReadersW_Call(smartcard, out, operation);
1615
0
      break;
1616
1617
0
    case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1618
0
      result = smartcard_IntroduceReaderGroupA_Call(smartcard, out, operation);
1619
0
      break;
1620
1621
0
    case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1622
0
      result = smartcard_IntroduceReaderGroupW_Call(smartcard, out, operation);
1623
0
      break;
1624
1625
0
    case SCARD_IOCTL_FORGETREADERGROUPA:
1626
0
      result = smartcard_ForgetReaderA_Call(smartcard, out, operation);
1627
0
      break;
1628
1629
0
    case SCARD_IOCTL_FORGETREADERGROUPW:
1630
0
      result = smartcard_ForgetReaderW_Call(smartcard, out, operation);
1631
0
      break;
1632
1633
0
    case SCARD_IOCTL_INTRODUCEREADERA:
1634
0
      result = smartcard_IntroduceReaderA_Call(smartcard, out, operation);
1635
0
      break;
1636
1637
0
    case SCARD_IOCTL_INTRODUCEREADERW:
1638
0
      result = smartcard_IntroduceReaderW_Call(smartcard, out, operation);
1639
0
      break;
1640
1641
0
    case SCARD_IOCTL_FORGETREADERA:
1642
0
      result = smartcard_ForgetReaderA_Call(smartcard, out, operation);
1643
0
      break;
1644
1645
0
    case SCARD_IOCTL_FORGETREADERW:
1646
0
      result = smartcard_ForgetReaderW_Call(smartcard, out, operation);
1647
0
      break;
1648
1649
0
    case SCARD_IOCTL_ADDREADERTOGROUPA:
1650
0
      result = smartcard_AddReaderToGroupA_Call(smartcard, out, operation);
1651
0
      break;
1652
1653
0
    case SCARD_IOCTL_ADDREADERTOGROUPW:
1654
0
      result = smartcard_AddReaderToGroupW_Call(smartcard, out, operation);
1655
0
      break;
1656
1657
0
    case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1658
0
      result = smartcard_RemoveReaderFromGroupA_Call(smartcard, out, operation);
1659
0
      break;
1660
1661
0
    case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1662
0
      result = smartcard_RemoveReaderFromGroupW_Call(smartcard, out, operation);
1663
0
      break;
1664
1665
0
    case SCARD_IOCTL_LOCATECARDSA:
1666
0
      result = smartcard_LocateCardsA_Call(smartcard, out, operation);
1667
0
      break;
1668
1669
0
    case SCARD_IOCTL_LOCATECARDSW:
1670
0
      result = smartcard_LocateCardsW_Call(smartcard, out, operation);
1671
0
      break;
1672
1673
0
    case SCARD_IOCTL_GETSTATUSCHANGEA:
1674
0
      result = smartcard_GetStatusChangeA_Call(smartcard, out, operation);
1675
0
      break;
1676
1677
0
    case SCARD_IOCTL_GETSTATUSCHANGEW:
1678
0
      result = smartcard_GetStatusChangeW_Call(smartcard, out, operation);
1679
0
      break;
1680
1681
0
    case SCARD_IOCTL_CANCEL:
1682
0
      result = smartcard_Cancel_Call(smartcard, out, operation);
1683
0
      break;
1684
1685
0
    case SCARD_IOCTL_CONNECTA:
1686
0
      result = smartcard_ConnectA_Call(smartcard, out, operation);
1687
0
      break;
1688
1689
0
    case SCARD_IOCTL_CONNECTW:
1690
0
      result = smartcard_ConnectW_Call(smartcard, out, operation);
1691
0
      break;
1692
1693
0
    case SCARD_IOCTL_RECONNECT:
1694
0
      result = smartcard_Reconnect_Call(smartcard, out, operation);
1695
0
      break;
1696
1697
0
    case SCARD_IOCTL_DISCONNECT:
1698
0
      result = smartcard_Disconnect_Call(smartcard, out, operation);
1699
0
      break;
1700
1701
0
    case SCARD_IOCTL_BEGINTRANSACTION:
1702
0
      result = smartcard_BeginTransaction_Call(smartcard, out, operation);
1703
0
      break;
1704
1705
0
    case SCARD_IOCTL_ENDTRANSACTION:
1706
0
      result = smartcard_EndTransaction_Call(smartcard, out, operation);
1707
0
      break;
1708
1709
0
    case SCARD_IOCTL_STATE:
1710
0
      result = smartcard_State_Call(smartcard, out, operation);
1711
0
      break;
1712
1713
0
    case SCARD_IOCTL_STATUSA:
1714
0
      result = smartcard_StatusA_Call(smartcard, out, operation);
1715
0
      break;
1716
1717
0
    case SCARD_IOCTL_STATUSW:
1718
0
      result = smartcard_StatusW_Call(smartcard, out, operation);
1719
0
      break;
1720
1721
0
    case SCARD_IOCTL_TRANSMIT:
1722
0
      result = smartcard_Transmit_Call(smartcard, out, operation);
1723
0
      break;
1724
1725
0
    case SCARD_IOCTL_CONTROL:
1726
0
      result = smartcard_Control_Call(smartcard, out, operation);
1727
0
      break;
1728
1729
0
    case SCARD_IOCTL_GETATTRIB:
1730
0
      result = smartcard_GetAttrib_Call(smartcard, out, operation);
1731
0
      break;
1732
1733
0
    case SCARD_IOCTL_SETATTRIB:
1734
0
      result = smartcard_SetAttrib_Call(smartcard, out, operation);
1735
0
      break;
1736
1737
0
    case SCARD_IOCTL_ACCESSSTARTEDEVENT:
1738
0
      result = smartcard_AccessStartedEvent_Call(smartcard, out, operation);
1739
0
      break;
1740
1741
0
    case SCARD_IOCTL_LOCATECARDSBYATRA:
1742
0
      result = smartcard_LocateCardsByATRA_Call(smartcard, out, operation);
1743
0
      break;
1744
1745
0
    case SCARD_IOCTL_LOCATECARDSBYATRW:
1746
0
      result = smartcard_LocateCardsW_Call(smartcard, out, operation);
1747
0
      break;
1748
1749
0
    case SCARD_IOCTL_READCACHEA:
1750
0
      result = smartcard_ReadCacheA_Call(smartcard, out, operation);
1751
0
      break;
1752
1753
0
    case SCARD_IOCTL_READCACHEW:
1754
0
      result = smartcard_ReadCacheW_Call(smartcard, out, operation);
1755
0
      break;
1756
1757
0
    case SCARD_IOCTL_WRITECACHEA:
1758
0
      result = smartcard_WriteCacheA_Call(smartcard, out, operation);
1759
0
      break;
1760
1761
0
    case SCARD_IOCTL_WRITECACHEW:
1762
0
      result = smartcard_WriteCacheW_Call(smartcard, out, operation);
1763
0
      break;
1764
1765
0
    case SCARD_IOCTL_GETTRANSMITCOUNT:
1766
0
      result = smartcard_GetTransmitCount_Call(smartcard, out, operation);
1767
0
      break;
1768
1769
0
    case SCARD_IOCTL_RELEASETARTEDEVENT:
1770
0
      result = smartcard_ReleaseStartedEvent_Call(smartcard, out, operation);
1771
0
      break;
1772
1773
0
    case SCARD_IOCTL_GETREADERICON:
1774
0
      result = smartcard_GetReaderIcon_Call(smartcard, out, operation);
1775
0
      break;
1776
1777
0
    case SCARD_IOCTL_GETDEVICETYPEID:
1778
0
      result = smartcard_GetDeviceTypeId_Call(smartcard, out, operation);
1779
0
      break;
1780
1781
0
    default:
1782
0
      result = STATUS_UNSUCCESSFUL;
1783
0
      break;
1784
0
  }
1785
1786
  /**
1787
   * [MS-RPCE] 2.2.6.3 Primitive Type Serialization
1788
   * The type MUST be aligned on an 8-byte boundary. If the size of the
1789
   * primitive type is not a multiple of 8 bytes, the data MUST be padded.
1790
   */
1791
1792
0
  if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
1793
0
      (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
1794
0
  {
1795
0
    offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
1796
0
    smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
1797
0
  }
1798
1799
0
  if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
1800
0
      (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
1801
0
      (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
1802
0
  {
1803
0
    WLog_WARN(TAG, "IRP failure: %s (0x%08" PRIX32 "), status: %s (0x%08" PRIX32 ")",
1804
0
              scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
1805
0
              SCardGetErrorString(result), result);
1806
0
  }
1807
1808
0
  *pIoStatus = STATUS_SUCCESS;
1809
1810
0
  if ((result & 0xC0000000L) == 0xC0000000L)
1811
0
  {
1812
    /* NTSTATUS error */
1813
0
    *pIoStatus = (UINT32)result;
1814
0
    WLog_WARN(TAG, "IRP failure: %s (0x%08" PRIX32 "), ntstatus: 0x%08" PRIX32 "",
1815
0
              scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, result);
1816
0
  }
1817
1818
0
  Stream_SealLength(out);
1819
0
  outputBufferLength = Stream_Length(out);
1820
0
  WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH - 4U);
1821
0
  outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1822
0
  WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1823
0
  objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
1824
0
  WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
1825
0
  WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
1826
0
  Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1827
  /* Device Control Response */
1828
0
  Stream_Write_UINT32(out, (UINT32)outputBufferLength); /* OutputBufferLength (4 bytes) */
1829
0
  smartcard_pack_common_type_header(out);               /* CommonTypeHeader (8 bytes) */
1830
0
  smartcard_pack_private_type_header(
1831
0
      out, (UINT32)objectBufferLength); /* PrivateTypeHeader (8 bytes) */
1832
0
  Stream_Write_INT32(out, result);      /* Result (4 bytes) */
1833
0
  Stream_SetPosition(out, Stream_Length(out));
1834
0
  return SCARD_S_SUCCESS;
1835
0
}
1836
1837
void context_free(void* arg)
1838
0
{
1839
0
  struct s_scard_context_element* element = arg;
1840
0
  if (!arg)
1841
0
    return;
1842
1843
0
  if (element->fn_free)
1844
0
    element->fn_free(element->context);
1845
0
  free(element);
1846
0
}
1847
1848
scard_call_context* smartcard_call_context_new(const rdpSettings* settings)
1849
0
{
1850
0
  wObject* obj = NULL;
1851
0
  scard_call_context* ctx = NULL;
1852
1853
0
  WINPR_ASSERT(settings);
1854
0
  ctx = calloc(1, sizeof(scard_call_context));
1855
0
  if (!ctx)
1856
0
    goto fail;
1857
1858
0
  ctx->stopEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
1859
0
  if (!ctx->stopEvent)
1860
0
    goto fail;
1861
1862
0
  ctx->names = LinkedList_New();
1863
0
  if (!ctx->names)
1864
0
    goto fail;
1865
1866
0
#if defined(WITH_SMARTCARD_EMULATE)
1867
0
  ctx->useEmulatedCard = freerdp_settings_get_bool(settings, FreeRDP_SmartcardEmulation);
1868
0
#endif
1869
1870
0
  if (ctx->useEmulatedCard)
1871
0
  {
1872
0
#if defined(WITH_SMARTCARD_EMULATE)
1873
0
    ctx->emulation = Emulate_New(settings);
1874
0
    if (!ctx->emulation)
1875
0
      goto fail;
1876
#else
1877
    WLog_ERR(TAG, "Smartcard emulation requested, but not supported!");
1878
    goto fail;
1879
#endif
1880
0
  }
1881
0
  else
1882
0
  {
1883
0
    const char* WinSCardModule = freerdp_settings_get_string(settings, FreeRDP_WinSCardModule);
1884
0
    if (WinSCardModule)
1885
0
    {
1886
0
      ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
1887
1888
0
      if (!ctx->hWinSCardLibrary)
1889
0
      {
1890
0
        WLog_ERR(TAG, "Failed to load WinSCard library: '%s'", WinSCardModule);
1891
0
        goto fail;
1892
0
      }
1893
1894
0
      if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
1895
0
        goto fail;
1896
0
      ctx->pWinSCardApi = &ctx->WinSCardApi;
1897
0
    }
1898
0
    else
1899
0
    {
1900
0
      ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
1901
0
    }
1902
1903
0
    if (!ctx->pWinSCardApi)
1904
0
    {
1905
0
      WLog_ERR(TAG, "Failed to load WinSCard API!");
1906
0
      goto fail;
1907
0
    }
1908
0
  }
1909
1910
0
  ctx->rgSCardContextList = HashTable_New(FALSE);
1911
0
  if (!ctx->rgSCardContextList)
1912
0
    goto fail;
1913
1914
0
  obj = HashTable_ValueObject(ctx->rgSCardContextList);
1915
0
  WINPR_ASSERT(obj);
1916
0
  obj->fnObjectFree = context_free;
1917
1918
0
  return ctx;
1919
0
fail:
1920
0
  WINPR_PRAGMA_DIAG_PUSH
1921
0
  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1922
0
  smartcard_call_context_free(ctx);
1923
0
  WINPR_PRAGMA_DIAG_POP
1924
0
  return NULL;
1925
0
}
1926
1927
void smartcard_call_context_free(scard_call_context* ctx)
1928
0
{
1929
0
  if (!ctx)
1930
0
    return;
1931
1932
0
  smartcard_call_context_signal_stop(ctx, FALSE);
1933
1934
0
  LinkedList_Free(ctx->names);
1935
0
  if (ctx->StartedEvent)
1936
0
  {
1937
0
    WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
1938
0
    wrap(ctx, SCardReleaseStartedEvent);
1939
0
  }
1940
1941
0
  if (ctx->useEmulatedCard)
1942
0
  {
1943
0
#ifdef WITH_SMARTCARD_EMULATE
1944
0
    if (ctx->emulation)
1945
0
    {
1946
0
      Emulate_Free(ctx->emulation);
1947
0
      ctx->emulation = NULL;
1948
0
    }
1949
0
#endif
1950
0
  }
1951
1952
0
  if (ctx->hWinSCardLibrary)
1953
0
  {
1954
0
    ZeroMemory(&ctx->WinSCardApi, sizeof(SCardApiFunctionTable));
1955
0
    FreeLibrary(ctx->hWinSCardLibrary);
1956
0
    ctx->hWinSCardLibrary = NULL;
1957
0
  }
1958
1959
0
  ctx->pWinSCardApi = NULL;
1960
1961
0
  HashTable_Free(ctx->rgSCardContextList);
1962
0
  CloseHandle(ctx->stopEvent);
1963
0
  free(ctx);
1964
0
}
1965
1966
BOOL smartcard_call_context_add(scard_call_context* ctx, const char* name)
1967
0
{
1968
0
  WINPR_ASSERT(ctx);
1969
0
  WINPR_ASSERT(name);
1970
0
  return LinkedList_AddLast(ctx->names, name);
1971
0
}
1972
1973
BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
1974
0
{
1975
0
  WINPR_ASSERT(ctx);
1976
0
  if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
1977
0
  {
1978
0
    wrap(ctx, SCardCancel, hContext);
1979
0
  }
1980
0
  return TRUE;
1981
0
}
1982
1983
BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
1984
0
{
1985
0
  WINPR_ASSERT(ctx);
1986
0
  wrap(ctx, SCardReleaseContext, hContext);
1987
0
  return TRUE;
1988
0
}
1989
1990
BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
1991
0
{
1992
0
  WINPR_ASSERT(ctx);
1993
1994
0
  HashTable_Clear(ctx->rgSCardContextList);
1995
0
  return TRUE;
1996
0
}
1997
1998
BOOL smarcard_call_set_callbacks(scard_call_context* ctx, void* userdata,
1999
                                 void* (*fn_new)(void*, SCARDCONTEXT), void (*fn_free)(void*))
2000
0
{
2001
0
  WINPR_ASSERT(ctx);
2002
0
  ctx->userdata = userdata;
2003
0
  ctx->fn_new = fn_new;
2004
0
  ctx->fn_free = fn_free;
2005
0
  return TRUE;
2006
0
}
2007
2008
void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2009
0
{
2010
0
  struct s_scard_context_element* element = NULL;
2011
2012
0
  WINPR_ASSERT(ctx);
2013
0
  element = HashTable_GetItemValue(ctx->rgSCardContextList, (void*)hContext);
2014
0
  if (!element)
2015
0
    return NULL;
2016
0
  return element->context;
2017
0
}
2018
2019
BOOL smartcard_call_is_configured(scard_call_context* ctx)
2020
0
{
2021
0
  WINPR_ASSERT(ctx);
2022
2023
0
#if defined(WITH_SMARTCARD_EMULATE)
2024
0
  if (ctx->useEmulatedCard)
2025
0
    return Emulate_IsConfigured(ctx->emulation);
2026
0
#endif
2027
2028
0
  return FALSE;
2029
0
}
2030
2031
BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
2032
0
{
2033
0
  WINPR_ASSERT(ctx);
2034
0
  if (!ctx->stopEvent)
2035
0
    return TRUE;
2036
2037
0
  if (reset)
2038
0
    return ResetEvent(ctx->stopEvent);
2039
0
  else
2040
0
    return SetEvent(ctx->stopEvent);
2041
0
}