Coverage Report

Created: 2026-04-12 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/libfreerdp/utils/smartcard_pack.c
Line
Count
Source
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Smart Card Structure Packing
4
 *
5
 * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 * Copyright 2015 Thincast Technologies GmbH
7
 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
8
 * Copyright 2020 Armin Novak <armin.novak@thincast.com>
9
 * Copyright 2020 Thincast Technologies GmbH
10
 *
11
 * Licensed under the Apache License, Version 2.0 (the "License");
12
 * you may not use this file except in compliance with the License.
13
 * You may obtain a copy of the License at
14
 *
15
 *     http://www.apache.org/licenses/LICENSE-2.0
16
 *
17
 * Unless required by applicable law or agreed to in writing, software
18
 * distributed under the License is distributed on an "AS IS" BASIS,
19
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
 * See the License for the specific language governing permissions and
21
 * limitations under the License.
22
 */
23
24
#include <freerdp/config.h>
25
26
#include <winpr/crt.h>
27
#include <winpr/print.h>
28
29
#include <freerdp/channels/scard.h>
30
#include <freerdp/utils/smartcard_pack.h>
31
#include "smartcard_pack.h"
32
33
#include <freerdp/log.h>
34
0
#define SCARD_TAG FREERDP_TAG("scard.pack")
35
36
static const DWORD g_LogLevel = WLOG_DEBUG;
37
38
static wLog* scard_log(void)
39
0
{
40
0
  static wLog* log = nullptr;
41
0
  if (!log)
42
0
    log = WLog_Get(SCARD_TAG);
43
0
  return log;
44
0
}
45
46
#define smartcard_unpack_redir_scard_context(log, s, context, index, ndr)                  \
47
0
  smartcard_unpack_redir_scard_context_((log), (s), (context), (index), (ndr), __FILE__, \
48
0
                                        __func__, __LINE__)
49
#define smartcard_unpack_redir_scard_handle(log, s, context, index)                          \
50
0
  smartcard_unpack_redir_scard_handle_((log), (s), (context), (index), __FILE__, __func__, \
51
0
                                       __LINE__)
52
53
static LONG smartcard_unpack_redir_scard_context_(wLog* log, wStream* s,
54
                                                  REDIR_SCARDCONTEXT* context, UINT32* index,
55
                                                  UINT32* ppbContextNdrPtr, const char* file,
56
                                                  const char* function, size_t line);
57
static LONG smartcard_pack_redir_scard_context(wLog* log, wStream* s,
58
                                               const REDIR_SCARDCONTEXT* context, DWORD* index);
59
static LONG smartcard_unpack_redir_scard_handle_(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle,
60
                                                 UINT32* index, const char* file,
61
                                                 const char* function, size_t line);
62
static LONG smartcard_pack_redir_scard_handle(wLog* log, wStream* s,
63
                                              const REDIR_SCARDHANDLE* handle, DWORD* index);
64
static LONG smartcard_unpack_redir_scard_context_ref(wLog* log, wStream* s, UINT32 pbContextNdrPtr,
65
                                                     REDIR_SCARDCONTEXT* context);
66
static LONG smartcard_pack_redir_scard_context_ref(wLog* log, wStream* s,
67
                                                   const REDIR_SCARDCONTEXT* context);
68
69
static LONG smartcard_unpack_redir_scard_handle_ref(wLog* log, wStream* s,
70
                                                    REDIR_SCARDHANDLE* handle);
71
static LONG smartcard_pack_redir_scard_handle_ref(wLog* log, wStream* s,
72
                                                  const REDIR_SCARDHANDLE* handle);
73
74
typedef enum
75
{
76
  NDR_PTR_FULL,
77
  NDR_PTR_SIMPLE,
78
  NDR_PTR_FIXED
79
} ndr_ptr_t;
80
81
/* Reads a NDR pointer and checks if the value read has the expected relative
82
 * addressing */
83
#define smartcard_ndr_pointer_read(log, s, index, ptr) \
84
0
  smartcard_ndr_pointer_read_((log), (s), (index), (ptr), __FILE__, __func__, __LINE__)
85
static BOOL smartcard_ndr_pointer_read_(wLog* log, wStream* s, UINT32* index, UINT32* ptr,
86
                                        const char* file, const char* fkt, size_t line)
87
0
{
88
0
  const UINT32 expect = 0x20000 + (*index) * 4;
89
0
  UINT32 ndrPtr = 0;
90
0
  WINPR_UNUSED(file);
91
0
  if (!s)
92
0
    return FALSE;
93
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
94
0
    return FALSE;
95
96
0
  Stream_Read_UINT32(s, ndrPtr); /* mszGroupsNdrPtr (4 bytes) */
97
0
  if (ptr)
98
0
    *ptr = ndrPtr;
99
0
  if (expect != ndrPtr)
100
0
  {
101
    /* Allow nullptr pointer if we read the result */
102
0
    if (ptr && (ndrPtr == 0))
103
0
      return TRUE;
104
0
    WLog_Print(log, WLOG_WARN,
105
0
               "[%s:%" PRIuz "] Read context pointer 0x%08" PRIx32 ", expected 0x%08" PRIx32,
106
0
               fkt, line, ndrPtr, expect);
107
0
    return FALSE;
108
0
  }
109
110
0
  (*index) = (*index) + 1;
111
0
  return TRUE;
112
0
}
113
114
static LONG smartcard_ndr_read_ex(wLog* log, wStream* s, BYTE** data, size_t min,
115
                                  size_t elementSize, ndr_ptr_t type, size_t* plen)
116
0
{
117
0
  size_t len = 0;
118
0
  size_t offset = 0;
119
0
  size_t len2 = 0;
120
0
  void* r = nullptr;
121
0
  size_t required = 0;
122
123
0
  *data = nullptr;
124
0
  if (plen)
125
0
    *plen = 0;
126
127
0
  switch (type)
128
0
  {
129
0
    case NDR_PTR_FULL:
130
0
      required = 12;
131
0
      break;
132
0
    case NDR_PTR_SIMPLE:
133
0
      required = 4;
134
0
      break;
135
0
    case NDR_PTR_FIXED:
136
0
      required = min;
137
0
      break;
138
0
    default:
139
0
      return STATUS_INVALID_PARAMETER;
140
0
  }
141
142
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, required))
143
0
    return STATUS_BUFFER_TOO_SMALL;
144
145
0
  switch (type)
146
0
  {
147
0
    case NDR_PTR_FULL:
148
0
      Stream_Read_UINT32(s, len);
149
0
      Stream_Read_UINT32(s, offset);
150
0
      Stream_Read_UINT32(s, len2);
151
0
      if (len != offset + len2)
152
0
      {
153
0
        WLog_Print(log, WLOG_ERROR,
154
0
                   "Invalid data when reading full NDR pointer: total=%" PRIuz
155
0
                   ", offset=%" PRIuz ", remaining=%" PRIuz,
156
0
                   len, offset, len2);
157
0
        return STATUS_BUFFER_TOO_SMALL;
158
0
      }
159
0
      break;
160
0
    case NDR_PTR_SIMPLE:
161
0
      Stream_Read_UINT32(s, len);
162
163
0
      if ((len != min) && (min > 0))
164
0
      {
165
0
        WLog_Print(log, WLOG_ERROR,
166
0
                   "Invalid data when reading simple NDR pointer: total=%" PRIuz
167
0
                   ", expected=%" PRIuz,
168
0
                   len, min);
169
0
        return STATUS_BUFFER_TOO_SMALL;
170
0
      }
171
0
      break;
172
0
    case NDR_PTR_FIXED:
173
0
      len = (UINT32)min;
174
0
      break;
175
0
    default:
176
0
      return STATUS_INVALID_PARAMETER;
177
0
  }
178
179
0
  if (min > len)
180
0
  {
181
0
    WLog_Print(log, WLOG_ERROR,
182
0
               "Invalid length read from NDR pointer, minimum %" PRIuz ", got %" PRIuz, min,
183
0
               len);
184
0
    return STATUS_DATA_ERROR;
185
0
  }
186
187
0
  if (len > SIZE_MAX / 2)
188
0
    return STATUS_BUFFER_TOO_SMALL;
189
190
0
  if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, len, elementSize))
191
0
    return STATUS_BUFFER_TOO_SMALL;
192
193
0
  len *= elementSize;
194
195
  /* Ensure proper '\0' termination for all kinds of unicode strings
196
   * as we do not know if the data from the wire contains one.
197
   */
198
0
  r = calloc(len + sizeof(WCHAR), sizeof(CHAR));
199
0
  if (!r)
200
0
    return SCARD_E_NO_MEMORY;
201
0
  Stream_Read(s, r, len);
202
0
  const LONG pad = smartcard_unpack_read_size_align(s, len, 4);
203
0
  if (pad < 0)
204
0
  {
205
0
    free(r);
206
0
    return STATUS_INVALID_PARAMETER;
207
0
  }
208
0
  len += (size_t)pad;
209
0
  *data = r;
210
0
  if (plen)
211
0
    *plen = len;
212
0
  return STATUS_SUCCESS;
213
0
}
214
215
static LONG smartcard_ndr_read(wLog* log, wStream* s, BYTE** data, size_t min, size_t elementSize,
216
                               ndr_ptr_t type)
217
0
{
218
0
  return smartcard_ndr_read_ex(log, s, data, min, elementSize, type, nullptr);
219
0
}
220
221
static BOOL smartcard_ndr_pointer_write(wStream* s, UINT32* index, DWORD length)
222
0
{
223
0
  const UINT32 ndrPtr = 0x20000 + (*index) * 4;
224
225
0
  if (!s)
226
0
    return FALSE;
227
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
228
0
    return FALSE;
229
230
0
  if (length > 0)
231
0
  {
232
0
    Stream_Write_UINT32(s, ndrPtr); /* mszGroupsNdrPtr (4 bytes) */
233
0
    (*index) = (*index) + 1;
234
0
  }
235
0
  else
236
0
    Stream_Write_UINT32(s, 0);
237
0
  return TRUE;
238
0
}
239
240
static LONG smartcard_ndr_write(wStream* s, const BYTE* data, UINT32 size, UINT32 elementSize,
241
                                ndr_ptr_t type)
242
0
{
243
0
  const UINT32 offset = 0;
244
0
  const UINT32 len = size;
245
0
  const UINT32 dataLen = size * elementSize;
246
0
  size_t required = 0;
247
248
0
  if (size == 0)
249
0
    return SCARD_S_SUCCESS;
250
251
0
  switch (type)
252
0
  {
253
0
    case NDR_PTR_FULL:
254
0
      required = 12;
255
0
      break;
256
0
    case NDR_PTR_SIMPLE:
257
0
      required = 4;
258
0
      break;
259
0
    case NDR_PTR_FIXED:
260
0
      required = 0;
261
0
      break;
262
0
    default:
263
0
      return SCARD_E_INVALID_PARAMETER;
264
0
  }
265
266
0
  if (!Stream_EnsureRemainingCapacity(s, required + dataLen + 4))
267
0
    return STATUS_BUFFER_TOO_SMALL;
268
269
0
  switch (type)
270
0
  {
271
0
    case NDR_PTR_FULL:
272
0
      Stream_Write_UINT32(s, len);
273
0
      Stream_Write_UINT32(s, offset);
274
0
      Stream_Write_UINT32(s, len);
275
0
      break;
276
0
    case NDR_PTR_SIMPLE:
277
0
      Stream_Write_UINT32(s, len);
278
0
      break;
279
0
    case NDR_PTR_FIXED:
280
0
      break;
281
0
    default:
282
0
      return SCARD_E_INVALID_PARAMETER;
283
0
  }
284
285
0
  if (data)
286
0
    Stream_Write(s, data, dataLen);
287
0
  else
288
0
    Stream_Zero(s, dataLen);
289
0
  return smartcard_pack_write_size_align(s, len, 4);
290
0
}
291
292
static LONG smartcard_ndr_write_state(wStream* s, const ReaderState_Return* data, UINT32 size,
293
                                      ndr_ptr_t type)
294
0
{
295
0
  union
296
0
  {
297
0
    const ReaderState_Return* reader;
298
0
    const BYTE* data;
299
0
  } cnv;
300
301
0
  WINPR_ASSERT(data || (size == 0));
302
0
  cnv.reader = data;
303
0
  return smartcard_ndr_write(s, cnv.data, size, sizeof(ReaderState_Return), type);
304
0
}
305
306
static LONG smartcard_ndr_read_atrmask(wLog* log, wStream* s, LocateCards_ATRMask** data,
307
                                       size_t min, ndr_ptr_t type)
308
0
{
309
0
  union
310
0
  {
311
0
    LocateCards_ATRMask** ppc;
312
0
    BYTE** ppv;
313
0
  } u;
314
0
  u.ppc = data;
315
0
  return smartcard_ndr_read(log, s, u.ppv, min, sizeof(LocateCards_ATRMask), type);
316
0
}
317
318
static LONG smartcard_ndr_read_fixed_string_a(wLog* log, wStream* s, CHAR** data, size_t min,
319
                                              ndr_ptr_t type)
320
0
{
321
0
  union
322
0
  {
323
0
    CHAR** ppc;
324
0
    BYTE** ppv;
325
0
  } u;
326
0
  u.ppc = data;
327
0
  return smartcard_ndr_read(log, s, u.ppv, min, sizeof(CHAR), type);
328
0
}
329
330
static LONG smartcard_ndr_read_fixed_string_w(wLog* log, wStream* s, WCHAR** data, size_t min,
331
                                              ndr_ptr_t type)
332
0
{
333
0
  union
334
0
  {
335
0
    WCHAR** ppc;
336
0
    BYTE** ppv;
337
0
  } u;
338
0
  u.ppc = data;
339
0
  return smartcard_ndr_read(log, s, u.ppv, min, sizeof(WCHAR), type);
340
0
}
341
342
static LONG smartcard_ndr_read_a(wLog* log, wStream* s, CHAR** data, ndr_ptr_t type)
343
0
{
344
0
  union
345
0
  {
346
0
    CHAR** ppc;
347
0
    BYTE** ppv;
348
0
  } u;
349
0
  u.ppc = data;
350
0
  return smartcard_ndr_read(log, s, u.ppv, 0, sizeof(CHAR), type);
351
0
}
352
353
static LONG smartcard_ndr_read_w(wLog* log, wStream* s, WCHAR** data, ndr_ptr_t type)
354
0
{
355
0
  union
356
0
  {
357
0
    WCHAR** ppc;
358
0
    BYTE** ppv;
359
0
  } u;
360
0
  u.ppc = data;
361
0
  return smartcard_ndr_read(log, s, u.ppv, 0, sizeof(WCHAR), type);
362
0
}
363
364
static LONG smartcard_ndr_read_u(wLog* log, wStream* s, UUID** data)
365
0
{
366
0
  union
367
0
  {
368
0
    UUID** ppc;
369
0
    BYTE** ppv;
370
0
  } u;
371
0
  u.ppc = data;
372
0
  return smartcard_ndr_read(log, s, u.ppv, 1, sizeof(UUID), NDR_PTR_FIXED);
373
0
}
374
375
static char* smartcard_convert_string_list(const void* in, size_t bytes, BOOL unicode)
376
0
{
377
0
  size_t length = 0;
378
0
  union
379
0
  {
380
0
    const void* pv;
381
0
    const char* sz;
382
0
    const WCHAR* wz;
383
0
  } string;
384
0
  char* mszA = nullptr;
385
386
0
  string.pv = in;
387
388
0
  if (bytes < 1)
389
0
    return nullptr;
390
391
0
  if (in == nullptr)
392
0
    return nullptr;
393
394
0
  if (unicode)
395
0
  {
396
0
    mszA = ConvertMszWCharNToUtf8Alloc(string.wz, bytes / sizeof(WCHAR), &length);
397
0
    if (!mszA)
398
0
      return nullptr;
399
0
  }
400
0
  else
401
0
  {
402
0
    mszA = (char*)calloc(bytes, sizeof(char));
403
0
    if (!mszA)
404
0
      return nullptr;
405
0
    CopyMemory(mszA, string.sz, bytes - 1);
406
0
    length = bytes;
407
0
  }
408
409
0
  if (length < 1)
410
0
  {
411
0
    free(mszA);
412
0
    return nullptr;
413
0
  }
414
0
  for (size_t index = 0; index < length - 1; index++)
415
0
  {
416
0
    if (mszA[index] == '\0')
417
0
      mszA[index] = ',';
418
0
  }
419
420
0
  return mszA;
421
0
}
422
423
WINPR_ATTR_MALLOC(free, 1)
424
static char* smartcard_create_msz_dump(const char* msz, size_t len)
425
0
{
426
0
  size_t bufferLen = len;
427
0
  char* buffer = calloc(len + 1, 1);
428
0
  if (!buffer)
429
0
    return nullptr;
430
431
0
  char* buf = buffer;
432
0
  const char* cur = msz;
433
434
0
  while ((len > 0) && cur && cur[0] != '\0' && (bufferLen > 0))
435
0
  {
436
0
    size_t clen = strnlen(cur, len);
437
0
    int rc = _snprintf(buf, bufferLen, "%s", cur);
438
0
    bufferLen -= (size_t)rc;
439
0
    buf += rc;
440
441
0
    cur += clen;
442
0
  }
443
444
0
  return buffer;
445
0
}
446
447
static void smartcard_msz_dump(wLog* log, DWORD level, const char* prefix, const void* data,
448
                               size_t len, BOOL wchar)
449
0
{
450
0
  if (!WLog_IsLevelActive(log, level))
451
0
    return;
452
453
0
  char* tmp = nullptr;
454
0
  const char* msz = WINPR_CXX_COMPAT_CAST(const char*, data);
455
0
  size_t mszlen = len;
456
0
  if (wchar)
457
0
  {
458
0
    tmp = ConvertMszWCharNToUtf8Alloc(data, len, &mszlen);
459
0
    msz = tmp;
460
0
  }
461
462
0
  char* array = smartcard_create_msz_dump(msz, mszlen);
463
0
  WLog_Print(log, level, "%s%s", prefix, array);
464
0
  free(array);
465
0
  free(tmp);
466
0
}
467
468
WINPR_ATTR_MALLOC(free, 1)
469
static char* smartcard_create_array_dump(const void* pd, size_t len)
470
0
{
471
0
  const BYTE* data = pd;
472
0
  int rc = 0;
473
474
0
  size_t bufferLen = len * 4;
475
0
  if (bufferLen < 32)
476
0
    bufferLen = 32;
477
0
  char* buffer = calloc(bufferLen + 1, 1);
478
0
  if (!buffer)
479
0
    return nullptr;
480
0
  char* start = buffer;
481
482
0
  WINPR_ASSERT(buffer || (bufferLen == 0));
483
484
0
  if (!data && (len > 0))
485
0
  {
486
0
    (void)_snprintf(buffer, bufferLen, "{ nullptr [%" PRIuz "] }", len);
487
0
    goto fail;
488
0
  }
489
490
0
  rc = _snprintf(buffer, bufferLen, "{ ");
491
0
  if ((rc < 0) || ((size_t)rc >= bufferLen))
492
0
    goto fail;
493
0
  buffer += rc;
494
0
  bufferLen -= (size_t)rc;
495
496
0
  for (size_t x = 0; x < len; x++)
497
0
  {
498
0
    rc = _snprintf(buffer, bufferLen, "%02X", data[x]);
499
0
    if ((rc < 0) || ((size_t)rc >= bufferLen))
500
0
      goto fail;
501
0
    buffer += rc;
502
0
    bufferLen -= (size_t)rc;
503
0
  }
504
505
0
  rc = _snprintf(buffer, bufferLen, " }");
506
0
  if ((rc < 0) || ((size_t)rc >= bufferLen))
507
0
    goto fail;
508
509
0
fail:
510
0
  return start;
511
0
}
512
513
WINPR_ATTR_FORMAT_ARG(3, 7)
514
static void smartcard_dump_array(wLog* log, DWORD level, WINPR_FORMAT_ARG const char* prefix,
515
                                 const char* postfix, const void* data, size_t len, ...)
516
0
{
517
0
  if (!WLog_IsLevelActive(log, level))
518
0
    return;
519
520
0
  char* buffer = smartcard_create_array_dump(data, len);
521
522
0
  char* fprefix = nullptr;
523
0
  size_t flen = 0;
524
0
  va_list ap = WINPR_C_ARRAY_INIT;
525
0
  va_start(ap, len);
526
0
  winpr_vasprintf(&fprefix, &flen, prefix, ap);
527
0
  va_end(ap);
528
0
  WLog_Print(log, level, "%s%s%s", prefix, buffer, postfix);
529
0
  free(buffer);
530
0
  free(fprefix);
531
0
}
532
533
static void smartcard_log_redir_handle(wLog* log, const REDIR_SCARDHANDLE* pHandle)
534
0
{
535
0
  WINPR_ASSERT(pHandle);
536
0
  smartcard_dump_array(log, g_LogLevel, "  hContext: ", "", pHandle->pbHandle, pHandle->cbHandle);
537
0
}
538
539
static void smartcard_log_context(wLog* log, const REDIR_SCARDCONTEXT* phContext)
540
0
{
541
0
  WINPR_ASSERT(phContext);
542
0
  smartcard_dump_array(log, g_LogLevel, "hContext: ", "", phContext->pbContext,
543
0
                       phContext->cbContext);
544
0
}
545
546
static void smartcard_trace_context_and_string_call_a(wLog* log, const char* name,
547
                                                      const REDIR_SCARDCONTEXT* phContext,
548
                                                      const CHAR* sz)
549
0
{
550
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
551
0
    return;
552
553
0
  WLog_Print(log, g_LogLevel, "%s {", name);
554
0
  smartcard_log_context(log, phContext);
555
0
  WLog_Print(log, g_LogLevel, "  sz=%s", sz);
556
557
0
  WLog_Print(log, g_LogLevel, "}");
558
0
}
559
560
static void smartcard_trace_context_and_string_call_w(wLog* log, const char* name,
561
                                                      const REDIR_SCARDCONTEXT* phContext,
562
                                                      const WCHAR* sz)
563
0
{
564
0
  char* tmp = nullptr;
565
566
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
567
0
    return;
568
569
0
  if (sz)
570
0
    tmp = ConvertWCharToUtf8Alloc(sz, nullptr);
571
572
0
  WLog_Print(log, g_LogLevel, "%s {", name);
573
0
  smartcard_log_context(log, phContext);
574
0
  WLog_Print(log, g_LogLevel, "  sz=%s", tmp);
575
0
  WLog_Print(log, g_LogLevel, "}");
576
0
  free(tmp);
577
0
}
578
579
static void smartcard_trace_context_call(wLog* log, const Context_Call* call, const char* name)
580
0
{
581
0
  WINPR_ASSERT(call);
582
583
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
584
0
    return;
585
586
0
  WLog_Print(log, g_LogLevel, "%s_Call {", name);
587
0
  smartcard_log_context(log, &call->handles.hContext);
588
589
0
  WLog_Print(log, g_LogLevel, "}");
590
0
}
591
592
static void smartcard_trace_list_reader_groups_call(wLog* log, const ListReaderGroups_Call* call,
593
                                                    BOOL unicode)
594
0
{
595
0
  WINPR_ASSERT(call);
596
597
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
598
0
    return;
599
600
0
  WLog_Print(log, g_LogLevel, "ListReaderGroups%s_Call {", unicode ? "W" : "A");
601
0
  smartcard_log_context(log, &call->handles.hContext);
602
603
0
  WLog_Print(log, g_LogLevel, "fmszGroupsIsNULL: %" PRId32 " cchGroups: 0x%08" PRIx32,
604
0
             call->fmszGroupsIsNULL, call->cchGroups);
605
0
  WLog_Print(log, g_LogLevel, "}");
606
0
}
607
608
static void dump_reader_states_return(wLog* log, const ReaderState_Return* rgReaderStates,
609
                                      UINT32 cReaders)
610
0
{
611
0
  WINPR_ASSERT(rgReaderStates || (cReaders == 0));
612
0
  for (UINT32 index = 0; index < cReaders; index++)
613
0
  {
614
0
    const ReaderState_Return* readerState = &rgReaderStates[index];
615
0
    char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
616
0
    char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
617
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
618
0
               szCurrentState, readerState->dwCurrentState);
619
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
620
0
               szEventState, readerState->dwEventState);
621
0
    free(szCurrentState);
622
0
    free(szEventState);
623
624
0
    smartcard_dump_array(log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { ", " }",
625
0
                         readerState->rgbAtr, readerState->cbAtr, index, readerState->cbAtr);
626
0
  }
627
0
}
628
629
static void dump_reader_states_a(wLog* log, const SCARD_READERSTATEA* rgReaderStates,
630
                                 UINT32 cReaders)
631
0
{
632
0
  WINPR_ASSERT(rgReaderStates || (cReaders == 0));
633
0
  for (UINT32 index = 0; index < cReaders; index++)
634
0
  {
635
0
    const SCARD_READERSTATEA* readerState = &rgReaderStates[index];
636
637
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: szReader: %s cbAtr: %" PRIu32 "", index,
638
0
               readerState->szReader, readerState->cbAtr);
639
0
    char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
640
0
    char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
641
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
642
0
               szCurrentState, readerState->dwCurrentState);
643
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
644
0
               szEventState, readerState->dwEventState);
645
0
    free(szCurrentState);
646
0
    free(szEventState);
647
648
0
    smartcard_dump_array(log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { ", " }",
649
0
                         readerState->rgbAtr, readerState->cbAtr, index, readerState->cbAtr);
650
0
  }
651
0
}
652
653
static void dump_reader_states_w(wLog* log, const SCARD_READERSTATEW* rgReaderStates,
654
                                 UINT32 cReaders)
655
0
{
656
0
  WINPR_ASSERT(rgReaderStates || (cReaders == 0));
657
0
  for (UINT32 index = 0; index < cReaders; index++)
658
0
  {
659
0
    const SCARD_READERSTATEW* readerState = &rgReaderStates[index];
660
0
    char* buffer = ConvertWCharToUtf8Alloc(readerState->szReader, nullptr);
661
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: szReader: %s cbAtr: %" PRIu32 "", index,
662
0
               buffer, readerState->cbAtr);
663
0
    free(buffer);
664
0
    char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
665
0
    char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
666
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
667
0
               szCurrentState, readerState->dwCurrentState);
668
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
669
0
               szEventState, readerState->dwEventState);
670
0
    free(szCurrentState);
671
0
    free(szEventState);
672
673
0
    smartcard_dump_array(log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { ", " }",
674
0
                         readerState->rgbAtr, readerState->cbAtr, index, readerState->cbAtr);
675
0
  }
676
0
}
677
678
static void smartcard_trace_get_status_change_w_call(wLog* log, const GetStatusChangeW_Call* call)
679
0
{
680
0
  WINPR_ASSERT(call);
681
682
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
683
0
    return;
684
685
0
  WLog_Print(log, g_LogLevel, "GetStatusChangeW_Call {");
686
0
  smartcard_log_context(log, &call->handles.hContext);
687
688
0
  WLog_Print(log, g_LogLevel, "dwTimeOut: 0x%08" PRIX32 " cReaders: %" PRIu32 "", call->dwTimeOut,
689
0
             call->cReaders);
690
691
0
  dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
692
693
0
  WLog_Print(log, g_LogLevel, "}");
694
0
}
695
696
static void smartcard_trace_list_reader_groups_return(wLog* log, const ListReaderGroups_Return* ret,
697
                                                      BOOL unicode)
698
0
{
699
0
  WINPR_ASSERT(ret);
700
701
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
702
0
    return;
703
704
0
  char* mszA = smartcard_convert_string_list(ret->msz, ret->cBytes, unicode);
705
706
0
  WLog_Print(log, g_LogLevel, "ListReaderGroups%s_Return {", unicode ? "W" : "A");
707
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIx32 ")",
708
0
             SCardGetErrorString(ret->ReturnCode),
709
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
710
0
  WLog_Print(log, g_LogLevel, "  cBytes: %" PRIu32 " msz: %s", ret->cBytes, mszA);
711
0
  WLog_Print(log, g_LogLevel, "}");
712
0
  free(mszA);
713
0
}
714
715
static void smartcard_trace_list_readers_call(wLog* log, const ListReaders_Call* call, BOOL unicode)
716
0
{
717
0
  WINPR_ASSERT(call);
718
719
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
720
0
    return;
721
722
0
  char* mszGroupsA = smartcard_convert_string_list(call->mszGroups, call->cBytes, unicode);
723
724
0
  WLog_Print(log, g_LogLevel, "ListReaders%s_Call {", unicode ? "W" : "A");
725
0
  smartcard_log_context(log, &call->handles.hContext);
726
727
0
  WLog_Print(log, g_LogLevel,
728
0
             "cBytes: %" PRIu32 " mszGroups: %s fmszReadersIsNULL: %" PRId32
729
0
             " cchReaders: 0x%08" PRIX32 "",
730
0
             call->cBytes, mszGroupsA, call->fmszReadersIsNULL, call->cchReaders);
731
0
  WLog_Print(log, g_LogLevel, "}");
732
733
0
  free(mszGroupsA);
734
0
}
735
736
static void smartcard_trace_locate_cards_by_atr_a_call(wLog* log,
737
                                                       const LocateCardsByATRA_Call* call)
738
0
{
739
0
  WINPR_ASSERT(call);
740
741
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
742
0
    return;
743
744
0
  WLog_Print(log, g_LogLevel, "LocateCardsByATRA_Call {");
745
0
  smartcard_log_context(log, &call->handles.hContext);
746
747
0
  dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
748
749
0
  WLog_Print(log, g_LogLevel, "}");
750
0
}
751
752
static void smartcard_trace_locate_cards_a_call(wLog* log, const LocateCardsA_Call* call)
753
0
{
754
0
  WINPR_ASSERT(call);
755
756
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
757
0
    return;
758
759
0
  WLog_Print(log, g_LogLevel, "LocateCardsA_Call {");
760
0
  smartcard_log_context(log, &call->handles.hContext);
761
0
  WLog_Print(log, g_LogLevel, " cBytes=%" PRIu32, call->cBytes);
762
0
  smartcard_msz_dump(log, g_LogLevel, " mszCards=", call->mszCards, call->cBytes, FALSE);
763
0
  WLog_Print(log, g_LogLevel, " cReaders=%" PRIu32, call->cReaders);
764
0
  dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
765
766
0
  WLog_Print(log, g_LogLevel, "}");
767
0
}
768
769
static void smartcard_trace_locate_cards_return(wLog* log, const LocateCards_Return* ret)
770
0
{
771
0
  WINPR_ASSERT(ret);
772
773
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
774
0
    return;
775
776
0
  WLog_Print(log, g_LogLevel, "LocateCards_Return {");
777
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
778
0
             SCardGetErrorString(ret->ReturnCode),
779
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
780
781
0
  if (ret->ReturnCode == SCARD_S_SUCCESS)
782
0
  {
783
0
    WLog_Print(log, g_LogLevel, "  cReaders=%" PRIu32, ret->cReaders);
784
0
  }
785
0
  WLog_Print(log, g_LogLevel, "}");
786
0
}
787
788
static void smartcard_trace_get_reader_icon_return(wLog* log, const GetReaderIcon_Return* ret)
789
0
{
790
0
  WINPR_ASSERT(ret);
791
792
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
793
0
    return;
794
795
0
  WLog_Print(log, g_LogLevel, "GetReaderIcon_Return {");
796
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
797
0
             SCardGetErrorString(ret->ReturnCode),
798
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
799
800
0
  if (ret->ReturnCode == SCARD_S_SUCCESS)
801
0
  {
802
0
    WLog_Print(log, g_LogLevel, "  cbDataLen=%" PRIu32, ret->cbDataLen);
803
0
  }
804
0
  WLog_Print(log, g_LogLevel, "}");
805
0
}
806
807
static void smartcard_trace_get_transmit_count_return(wLog* log, const GetTransmitCount_Return* ret)
808
0
{
809
0
  WINPR_ASSERT(ret);
810
811
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
812
0
    return;
813
814
0
  WLog_Print(log, g_LogLevel, "GetTransmitCount_Return {");
815
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
816
0
             SCardGetErrorString(ret->ReturnCode),
817
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
818
819
0
  WLog_Print(log, g_LogLevel, "  cTransmitCount=%" PRIu32, ret->cTransmitCount);
820
0
  WLog_Print(log, g_LogLevel, "}");
821
0
}
822
823
static void smartcard_trace_read_cache_return(wLog* log, const ReadCache_Return* ret)
824
0
{
825
0
  WINPR_ASSERT(ret);
826
827
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
828
0
    return;
829
830
0
  WLog_Print(log, g_LogLevel, "ReadCache_Return {");
831
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
832
0
             SCardGetErrorString(ret->ReturnCode),
833
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
834
835
0
  if (ret->ReturnCode == SCARD_S_SUCCESS)
836
0
  {
837
0
    WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, ret->cbDataLen);
838
0
    smartcard_dump_array(log, g_LogLevel, "  cbData: ", "", ret->pbData, ret->cbDataLen);
839
0
  }
840
0
  WLog_Print(log, g_LogLevel, "}");
841
0
}
842
843
static void smartcard_trace_locate_cards_w_call(wLog* log, const LocateCardsW_Call* call)
844
0
{
845
0
  WINPR_ASSERT(call);
846
847
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
848
0
    return;
849
850
0
  WLog_Print(log, g_LogLevel, "LocateCardsW_Call {");
851
0
  smartcard_log_context(log, &call->handles.hContext);
852
0
  WLog_Print(log, g_LogLevel, " cBytes=%" PRIu32, call->cBytes);
853
0
  smartcard_msz_dump(log, g_LogLevel, " sz2=", call->mszCards, call->cBytes, TRUE);
854
0
  WLog_Print(log, g_LogLevel, " cReaders=%" PRIu32, call->cReaders);
855
0
  dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
856
0
  WLog_Print(log, g_LogLevel, "}");
857
0
}
858
859
static void smartcard_trace_list_readers_return(wLog* log, const ListReaders_Return* ret,
860
                                                BOOL unicode)
861
0
{
862
0
  WINPR_ASSERT(ret);
863
864
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
865
0
    return;
866
867
0
  WLog_Print(log, g_LogLevel, "ListReaders%s_Return {", unicode ? "W" : "A");
868
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
869
0
             SCardGetErrorString(ret->ReturnCode),
870
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
871
872
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
873
0
  {
874
0
    WLog_Print(log, g_LogLevel, "}");
875
0
    return;
876
0
  }
877
878
0
  char* mszA = smartcard_convert_string_list(ret->msz, ret->cBytes, unicode);
879
880
0
  WLog_Print(log, g_LogLevel, "  cBytes: %" PRIu32 " msz: %s", ret->cBytes, mszA);
881
0
  WLog_Print(log, g_LogLevel, "}");
882
0
  free(mszA);
883
0
}
884
885
static void smartcard_trace_get_status_change_return(wLog* log, const GetStatusChange_Return* ret,
886
                                                     BOOL unicode)
887
0
{
888
0
  WINPR_ASSERT(ret);
889
890
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
891
0
    return;
892
893
0
  WLog_Print(log, g_LogLevel, "GetStatusChange%s_Return {", unicode ? "W" : "A");
894
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
895
0
             SCardGetErrorString(ret->ReturnCode),
896
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
897
0
  WLog_Print(log, g_LogLevel, "  cReaders: %" PRIu32 "", ret->cReaders);
898
899
0
  dump_reader_states_return(log, ret->rgReaderStates, ret->cReaders);
900
901
0
  if (!ret->rgReaderStates && (ret->cReaders > 0))
902
0
  {
903
0
    WLog_Print(log, g_LogLevel, "    [INVALID STATE] rgReaderStates=nullptr, cReaders=%" PRIu32,
904
0
               ret->cReaders);
905
0
  }
906
0
  else if (ret->ReturnCode != SCARD_S_SUCCESS)
907
0
  {
908
0
    WLog_Print(log, g_LogLevel, "    [INVALID RETURN] rgReaderStates, cReaders=%" PRIu32,
909
0
               ret->cReaders);
910
0
  }
911
0
  else
912
0
  {
913
0
    for (UINT32 index = 0; index < ret->cReaders; index++)
914
0
    {
915
0
      const ReaderState_Return* rgReaderState = &(ret->rgReaderStates[index]);
916
0
      char* szCurrentState = SCardGetReaderStateString(rgReaderState->dwCurrentState);
917
0
      char* szEventState = SCardGetReaderStateString(rgReaderState->dwEventState);
918
0
      WLog_Print(log, g_LogLevel, "    [%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")",
919
0
                 index, szCurrentState, rgReaderState->dwCurrentState);
920
0
      WLog_Print(log, g_LogLevel, "    [%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")",
921
0
                 index, szEventState, rgReaderState->dwEventState);
922
0
      smartcard_dump_array(
923
0
          log, g_LogLevel, "    [%" PRIu32 "]: cbAtr: %" PRIu32 " rgbAtr: ", "",
924
0
          rgReaderState->rgbAtr, rgReaderState->cbAtr, index, rgReaderState->cbAtr);
925
0
      free(szCurrentState);
926
0
      free(szEventState);
927
0
    }
928
0
  }
929
930
0
  WLog_Print(log, g_LogLevel, "}");
931
0
}
932
933
static void smartcard_trace_context_and_two_strings_a_call(wLog* log,
934
                                                           const ContextAndTwoStringA_Call* call)
935
0
{
936
0
  WINPR_ASSERT(call);
937
938
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
939
0
    return;
940
941
0
  WLog_Print(log, g_LogLevel, "ContextAndTwoStringW_Call {");
942
0
  smartcard_log_context(log, &call->handles.hContext);
943
0
  WLog_Print(log, g_LogLevel, " sz1=%s", call->sz1);
944
0
  WLog_Print(log, g_LogLevel, " sz2=%s", call->sz2);
945
0
  WLog_Print(log, g_LogLevel, "}");
946
0
}
947
948
static void smartcard_trace_context_and_two_strings_w_call(wLog* log,
949
                                                           const ContextAndTwoStringW_Call* call)
950
0
{
951
0
  WINPR_ASSERT(call);
952
0
  char sz1[1024] = WINPR_C_ARRAY_INIT;
953
0
  char sz2[1024] = WINPR_C_ARRAY_INIT;
954
955
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
956
0
    return;
957
0
  if (call->sz1)
958
0
    (void)ConvertWCharToUtf8(call->sz1, sz1, ARRAYSIZE(sz1));
959
0
  if (call->sz2)
960
0
    (void)ConvertWCharToUtf8(call->sz2, sz2, ARRAYSIZE(sz2));
961
962
0
  WLog_Print(log, g_LogLevel, "ContextAndTwoStringW_Call {");
963
0
  smartcard_log_context(log, &call->handles.hContext);
964
0
  WLog_Print(log, g_LogLevel, " sz1=%s", sz1);
965
0
  WLog_Print(log, g_LogLevel, " sz2=%s", sz2);
966
0
  WLog_Print(log, g_LogLevel, "}");
967
0
}
968
969
static void smartcard_trace_get_transmit_count_call(wLog* log, const GetTransmitCount_Call* call)
970
0
{
971
0
  WINPR_ASSERT(call);
972
973
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
974
0
    return;
975
976
0
  WLog_Print(log, g_LogLevel, "GetTransmitCount_Call {");
977
0
  smartcard_log_context(log, &call->handles.hContext);
978
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
979
980
0
  WLog_Print(log, g_LogLevel, "}");
981
0
}
982
983
static void smartcard_trace_write_cache_a_call(wLog* log, const WriteCacheA_Call* call)
984
0
{
985
0
  WINPR_ASSERT(call);
986
987
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
988
0
    return;
989
990
0
  WLog_Print(log, g_LogLevel, "WriteCacheA_Call {");
991
992
0
  WLog_Print(log, g_LogLevel, "  szLookupName=%s", call->szLookupName);
993
994
0
  smartcard_log_context(log, &call->Common.handles.hContext);
995
0
  smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
996
0
                       sizeof(UUID));
997
0
  WLog_Print(log, g_LogLevel, "  FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
998
0
  WLog_Print(log, g_LogLevel, "  cbDataLen=%" PRIu32, call->Common.cbDataLen);
999
0
  smartcard_dump_array(log, g_LogLevel, "  pbData=", "", call->Common.pbData,
1000
0
                       call->Common.cbDataLen);
1001
0
  WLog_Print(log, g_LogLevel, "}");
1002
0
}
1003
1004
static void smartcard_trace_write_cache_w_call(wLog* log, const WriteCacheW_Call* call)
1005
0
{
1006
0
  WINPR_ASSERT(call);
1007
0
  char tmp[1024] = WINPR_C_ARRAY_INIT;
1008
1009
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1010
0
    return;
1011
1012
0
  WLog_Print(log, g_LogLevel, "WriteCacheW_Call {");
1013
1014
0
  if (call->szLookupName)
1015
0
    (void)ConvertWCharToUtf8(call->szLookupName, tmp, ARRAYSIZE(tmp));
1016
0
  WLog_Print(log, g_LogLevel, "  szLookupName=%s", tmp);
1017
1018
0
  smartcard_log_context(log, &call->Common.handles.hContext);
1019
0
  smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1020
0
                       sizeof(UUID));
1021
0
  WLog_Print(log, g_LogLevel, "  FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1022
0
  WLog_Print(log, g_LogLevel, "  cbDataLen=%" PRIu32, call->Common.cbDataLen);
1023
0
  smartcard_dump_array(log, g_LogLevel, "  pbData=", "", call->Common.pbData,
1024
0
                       call->Common.cbDataLen);
1025
0
  WLog_Print(log, g_LogLevel, "}");
1026
0
}
1027
1028
static void smartcard_trace_read_cache_a_call(wLog* log, const ReadCacheA_Call* call)
1029
0
{
1030
0
  WINPR_ASSERT(call);
1031
1032
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1033
0
    return;
1034
1035
0
  WLog_Print(log, g_LogLevel, "ReadCacheA_Call {");
1036
1037
0
  WLog_Print(log, g_LogLevel, "  szLookupName=%s", call->szLookupName);
1038
0
  smartcard_log_context(log, &call->Common.handles.hContext);
1039
0
  smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1040
0
                       sizeof(UUID));
1041
0
  WLog_Print(log, g_LogLevel, "  FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1042
0
  WLog_Print(log, g_LogLevel, "  fPbDataIsNULL=%" PRId32, call->Common.fPbDataIsNULL);
1043
0
  WLog_Print(log, g_LogLevel, "  cbDataLen=%" PRIu32, call->Common.cbDataLen);
1044
1045
0
  WLog_Print(log, g_LogLevel, "}");
1046
0
}
1047
1048
static void smartcard_trace_read_cache_w_call(wLog* log, const ReadCacheW_Call* call)
1049
0
{
1050
0
  WINPR_ASSERT(call);
1051
0
  char tmp[1024] = WINPR_C_ARRAY_INIT;
1052
1053
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1054
0
    return;
1055
1056
0
  WLog_Print(log, g_LogLevel, "ReadCacheW_Call {");
1057
0
  if (call->szLookupName)
1058
0
    (void)ConvertWCharToUtf8(call->szLookupName, tmp, ARRAYSIZE(tmp));
1059
0
  WLog_Print(log, g_LogLevel, "  szLookupName=%s", tmp);
1060
1061
0
  smartcard_log_context(log, &call->Common.handles.hContext);
1062
0
  smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1063
0
                       sizeof(UUID));
1064
0
  WLog_Print(log, g_LogLevel, "  FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1065
0
  WLog_Print(log, g_LogLevel, "  fPbDataIsNULL=%" PRId32, call->Common.fPbDataIsNULL);
1066
0
  WLog_Print(log, g_LogLevel, "  cbDataLen=%" PRIu32, call->Common.cbDataLen);
1067
1068
0
  WLog_Print(log, g_LogLevel, "}");
1069
0
}
1070
1071
static void smartcard_trace_transmit_call(wLog* log, const Transmit_Call* call)
1072
0
{
1073
0
  WINPR_ASSERT(call);
1074
0
  UINT32 cbExtraBytes = 0;
1075
0
  BYTE* pbExtraBytes = nullptr;
1076
1077
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1078
0
    return;
1079
1080
0
  WLog_Print(log, g_LogLevel, "Transmit_Call {");
1081
0
  smartcard_log_context(log, &call->handles.hContext);
1082
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1083
1084
0
  if (call->pioSendPci)
1085
0
  {
1086
0
    cbExtraBytes = (UINT32)(call->pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1087
0
    pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
1088
0
    WLog_Print(log, g_LogLevel, "pioSendPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1089
0
               call->pioSendPci->dwProtocol, cbExtraBytes);
1090
1091
0
    if (cbExtraBytes)
1092
0
    {
1093
0
      smartcard_dump_array(log, g_LogLevel, "pbExtraBytes: ", "", pbExtraBytes, cbExtraBytes);
1094
0
    }
1095
0
  }
1096
0
  else
1097
0
  {
1098
0
    WLog_Print(log, g_LogLevel, "pioSendPci: null");
1099
0
  }
1100
1101
0
  WLog_Print(log, g_LogLevel, "cbSendLength: %" PRIu32 "", call->cbSendLength);
1102
1103
0
  if (call->pbSendBuffer)
1104
0
  {
1105
0
    smartcard_dump_array(log, g_LogLevel, "pbSendBuffer: ", "", call->pbSendBuffer,
1106
0
                         call->cbSendLength);
1107
0
  }
1108
0
  else
1109
0
  {
1110
0
    WLog_Print(log, g_LogLevel, "pbSendBuffer: null");
1111
0
  }
1112
1113
0
  if (call->pioRecvPci)
1114
0
  {
1115
0
    cbExtraBytes = (UINT32)(call->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1116
0
    pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
1117
0
    WLog_Print(log, g_LogLevel, "pioRecvPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1118
0
               call->pioRecvPci->dwProtocol, cbExtraBytes);
1119
1120
0
    if (cbExtraBytes)
1121
0
    {
1122
0
      smartcard_dump_array(log, g_LogLevel, "pbExtraBytes: ", "", pbExtraBytes, cbExtraBytes);
1123
0
    }
1124
0
  }
1125
0
  else
1126
0
  {
1127
0
    WLog_Print(log, g_LogLevel, "pioRecvPci: null");
1128
0
  }
1129
1130
0
  WLog_Print(log, g_LogLevel, "fpbRecvBufferIsNULL: %" PRId32 " cbRecvLength: %" PRIu32 "",
1131
0
             call->fpbRecvBufferIsNULL, call->cbRecvLength);
1132
0
  WLog_Print(log, g_LogLevel, "}");
1133
0
}
1134
1135
static void smartcard_trace_locate_cards_by_atr_w_call(wLog* log,
1136
                                                       const LocateCardsByATRW_Call* call)
1137
0
{
1138
0
  WINPR_ASSERT(call);
1139
1140
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1141
0
    return;
1142
1143
0
  WLog_Print(log, g_LogLevel, "LocateCardsByATRW_Call {");
1144
0
  smartcard_log_context(log, &call->handles.hContext);
1145
1146
0
  dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
1147
1148
0
  WLog_Print(log, g_LogLevel, "}");
1149
0
}
1150
1151
static void smartcard_trace_transmit_return(wLog* log, const Transmit_Return* ret)
1152
0
{
1153
0
  WINPR_ASSERT(ret);
1154
0
  UINT32 cbExtraBytes = 0;
1155
0
  BYTE* pbExtraBytes = nullptr;
1156
1157
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1158
0
    return;
1159
1160
0
  WLog_Print(log, g_LogLevel, "Transmit_Return {");
1161
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1162
0
             SCardGetErrorString(ret->ReturnCode),
1163
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1164
1165
0
  if (ret->pioRecvPci)
1166
0
  {
1167
0
    cbExtraBytes = (UINT32)(ret->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1168
0
    pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
1169
0
    WLog_Print(log, g_LogLevel,
1170
0
               "  pioRecvPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1171
0
               ret->pioRecvPci->dwProtocol, cbExtraBytes);
1172
1173
0
    if (cbExtraBytes)
1174
0
    {
1175
0
      smartcard_dump_array(log, g_LogLevel, "  pbExtraBytes: ", "", pbExtraBytes,
1176
0
                           cbExtraBytes);
1177
0
    }
1178
0
  }
1179
0
  else
1180
0
  {
1181
0
    WLog_Print(log, g_LogLevel, "  pioRecvPci: null");
1182
0
  }
1183
1184
0
  WLog_Print(log, g_LogLevel, "  cbRecvLength: %" PRIu32 "", ret->cbRecvLength);
1185
1186
0
  if (ret->pbRecvBuffer)
1187
0
  {
1188
0
    smartcard_dump_array(log, g_LogLevel, "  pbRecvBuffer: ", "", ret->pbRecvBuffer,
1189
0
                         ret->cbRecvLength);
1190
0
  }
1191
0
  else
1192
0
  {
1193
0
    WLog_Print(log, g_LogLevel, "  pbRecvBuffer: null");
1194
0
  }
1195
1196
0
  WLog_Print(log, g_LogLevel, "}");
1197
0
}
1198
1199
static void smartcard_trace_control_return(wLog* log, const Control_Return* ret)
1200
0
{
1201
0
  WINPR_ASSERT(ret);
1202
1203
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1204
0
    return;
1205
1206
0
  WLog_Print(log, g_LogLevel, "Control_Return {");
1207
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1208
0
             SCardGetErrorString(ret->ReturnCode),
1209
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1210
0
  WLog_Print(log, g_LogLevel, "  cbOutBufferSize: %" PRIu32 "", ret->cbOutBufferSize);
1211
1212
0
  if (ret->pvOutBuffer)
1213
0
  {
1214
0
    smartcard_dump_array(log, g_LogLevel, "pvOutBuffer: ", "", ret->pvOutBuffer,
1215
0
                         ret->cbOutBufferSize);
1216
0
  }
1217
0
  else
1218
0
  {
1219
0
    WLog_Print(log, g_LogLevel, "pvOutBuffer: null");
1220
0
  }
1221
1222
0
  WLog_Print(log, g_LogLevel, "}");
1223
0
}
1224
1225
static void smartcard_trace_control_call(wLog* log, const Control_Call* call)
1226
0
{
1227
0
  WINPR_ASSERT(call);
1228
1229
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1230
0
    return;
1231
1232
0
  WLog_Print(log, g_LogLevel, "Control_Call {");
1233
0
  smartcard_log_context(log, &call->handles.hContext);
1234
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1235
1236
0
  WLog_Print(log, g_LogLevel,
1237
0
             "dwControlCode: 0x%08" PRIX32 " cbInBufferSize: %" PRIu32
1238
0
             " fpvOutBufferIsNULL: %" PRId32 " cbOutBufferSize: %" PRIu32 "",
1239
0
             call->dwControlCode, call->cbInBufferSize, call->fpvOutBufferIsNULL,
1240
0
             call->cbOutBufferSize);
1241
1242
0
  if (call->pvInBuffer)
1243
0
  {
1244
0
    smartcard_dump_array(log, WLOG_DEBUG, "pbInBuffer: ", "", call->pvInBuffer,
1245
0
                         call->cbInBufferSize);
1246
0
  }
1247
0
  else
1248
0
  {
1249
0
    WLog_Print(log, g_LogLevel, "pvInBuffer: null");
1250
0
  }
1251
1252
0
  WLog_Print(log, g_LogLevel, "}");
1253
0
}
1254
1255
static void smartcard_trace_set_attrib_call(wLog* log, const SetAttrib_Call* call)
1256
0
{
1257
0
  WINPR_ASSERT(call);
1258
1259
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1260
0
    return;
1261
1262
0
  WLog_Print(log, g_LogLevel, "GetAttrib_Call {");
1263
0
  smartcard_log_context(log, &call->handles.hContext);
1264
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1265
0
  WLog_Print(log, g_LogLevel, "dwAttrId: 0x%08" PRIX32, call->dwAttrId);
1266
0
  WLog_Print(log, g_LogLevel, "cbAttrLen: 0x%08" PRIx32, call->cbAttrLen);
1267
0
  smartcard_dump_array(log, g_LogLevel, "pbAttr: ", "", call->pbAttr, call->cbAttrLen);
1268
0
  WLog_Print(log, g_LogLevel, "}");
1269
0
}
1270
1271
static void smartcard_trace_get_attrib_return(wLog* log, const GetAttrib_Return* ret,
1272
                                              DWORD dwAttrId)
1273
0
{
1274
0
  WINPR_ASSERT(ret);
1275
1276
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1277
0
    return;
1278
1279
0
  WLog_Print(log, g_LogLevel, "GetAttrib_Return {");
1280
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1281
0
             SCardGetErrorString(ret->ReturnCode),
1282
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1283
0
  WLog_Print(log, g_LogLevel, "  dwAttrId: %s (0x%08" PRIX32 ") cbAttrLen: 0x%08" PRIX32 "",
1284
0
             SCardGetAttributeString(dwAttrId), dwAttrId, ret->cbAttrLen);
1285
0
  smartcard_dump_array(log, g_LogLevel, "  ", "", ret->pbAttr, ret->cbAttrLen);
1286
1287
0
  WLog_Print(log, g_LogLevel, "}");
1288
0
}
1289
1290
static void smartcard_trace_get_attrib_call(wLog* log, const GetAttrib_Call* call)
1291
0
{
1292
0
  WINPR_ASSERT(call);
1293
1294
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1295
0
    return;
1296
1297
0
  WLog_Print(log, g_LogLevel, "GetAttrib_Call {");
1298
0
  smartcard_log_context(log, &call->handles.hContext);
1299
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1300
1301
0
  WLog_Print(log, g_LogLevel,
1302
0
             "dwAttrId: %s (0x%08" PRIX32 ") fpbAttrIsNULL: %" PRId32 " cbAttrLen: 0x%08" PRIX32
1303
0
             "",
1304
0
             SCardGetAttributeString(call->dwAttrId), call->dwAttrId, call->fpbAttrIsNULL,
1305
0
             call->cbAttrLen);
1306
0
  WLog_Print(log, g_LogLevel, "}");
1307
0
}
1308
1309
static void smartcard_trace_status_call(wLog* log, const Status_Call* call, BOOL unicode)
1310
0
{
1311
0
  WINPR_ASSERT(call);
1312
1313
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1314
0
    return;
1315
1316
0
  WLog_Print(log, g_LogLevel, "Status%s_Call {", unicode ? "W" : "A");
1317
0
  smartcard_log_context(log, &call->handles.hContext);
1318
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1319
1320
0
  WLog_Print(log, g_LogLevel,
1321
0
             "fmszReaderNamesIsNULL: %" PRId32 " cchReaderLen: %" PRIu32 " cbAtrLen: %" PRIu32 "",
1322
0
             call->fmszReaderNamesIsNULL, call->cchReaderLen, call->cbAtrLen);
1323
0
  WLog_Print(log, g_LogLevel, "}");
1324
0
}
1325
1326
static void smartcard_trace_status_return(wLog* log, const Status_Return* ret, BOOL unicode)
1327
0
{
1328
0
  WINPR_ASSERT(ret);
1329
0
  char* mszReaderNamesA = nullptr;
1330
0
  DWORD cBytes = 0;
1331
1332
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1333
0
    return;
1334
0
  cBytes = ret->cBytes;
1335
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
1336
0
    cBytes = 0;
1337
0
  if (cBytes == SCARD_AUTOALLOCATE)
1338
0
    cBytes = 0;
1339
0
  mszReaderNamesA = smartcard_convert_string_list(ret->mszReaderNames, cBytes, unicode);
1340
1341
0
  WLog_Print(log, g_LogLevel, "Status%s_Return {", unicode ? "W" : "A");
1342
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1343
0
             SCardGetErrorString(ret->ReturnCode),
1344
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1345
0
  WLog_Print(log, g_LogLevel, "  dwState: %s (0x%08" PRIX32 ") dwProtocol: %s (0x%08" PRIX32 ")",
1346
0
             SCardGetCardStateString(ret->dwState), ret->dwState,
1347
0
             SCardGetProtocolString(ret->dwProtocol), ret->dwProtocol);
1348
1349
0
  WLog_Print(log, g_LogLevel, "  cBytes: %" PRIu32 " mszReaderNames: %s", ret->cBytes,
1350
0
             mszReaderNamesA);
1351
1352
0
  smartcard_dump_array(log, g_LogLevel, "  cbAtrLen: %" PRIu32 " pbAtr: ", "", ret->pbAtr,
1353
0
                       ret->cbAtrLen, ret->cbAtrLen);
1354
0
  WLog_Print(log, g_LogLevel, "}");
1355
0
  free(mszReaderNamesA);
1356
0
}
1357
1358
static void smartcard_trace_state_return(wLog* log, const State_Return* ret)
1359
0
{
1360
0
  WINPR_ASSERT(ret);
1361
0
  char* state = nullptr;
1362
1363
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1364
0
    return;
1365
1366
0
  state = SCardGetReaderStateString(ret->dwState);
1367
0
  WLog_Print(log, g_LogLevel, "Reconnect_Return {");
1368
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1369
0
             SCardGetErrorString(ret->ReturnCode),
1370
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1371
0
  WLog_Print(log, g_LogLevel, "  dwState:    %s (0x%08" PRIX32 ")", state, ret->dwState);
1372
0
  WLog_Print(log, g_LogLevel, "  dwProtocol: %s (0x%08" PRIX32 ")",
1373
0
             SCardGetProtocolString(ret->dwProtocol), ret->dwProtocol);
1374
0
  WLog_Print(log, g_LogLevel, "  cbAtrLen:      (0x%08" PRIX32 ")", ret->cbAtrLen);
1375
0
  smartcard_dump_array(log, g_LogLevel, "  rgAtr:      ", "", ret->rgAtr, sizeof(ret->rgAtr));
1376
0
  WLog_Print(log, g_LogLevel, "}");
1377
0
  free(state);
1378
0
}
1379
1380
static void smartcard_trace_reconnect_return(wLog* log, const Reconnect_Return* ret)
1381
0
{
1382
0
  WINPR_ASSERT(ret);
1383
1384
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1385
0
    return;
1386
1387
0
  WLog_Print(log, g_LogLevel, "Reconnect_Return {");
1388
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1389
0
             SCardGetErrorString(ret->ReturnCode),
1390
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1391
0
  WLog_Print(log, g_LogLevel, "  dwActiveProtocol: %s (0x%08" PRIX32 ")",
1392
0
             SCardGetProtocolString(ret->dwActiveProtocol), ret->dwActiveProtocol);
1393
0
  WLog_Print(log, g_LogLevel, "}");
1394
0
}
1395
1396
static void smartcard_trace_connect_a_call(wLog* log, const ConnectA_Call* call)
1397
0
{
1398
0
  WINPR_ASSERT(call);
1399
1400
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1401
0
    return;
1402
1403
0
  WLog_Print(log, g_LogLevel, "ConnectA_Call {");
1404
0
  smartcard_log_context(log, &call->Common.handles.hContext);
1405
1406
0
  WLog_Print(log, g_LogLevel,
1407
0
             "szReader: %s dwShareMode: %s (0x%08" PRIX32
1408
0
             ") dwPreferredProtocols: %s (0x%08" PRIX32 ")",
1409
0
             call->szReader, SCardGetShareModeString(call->Common.dwShareMode),
1410
0
             call->Common.dwShareMode, SCardGetProtocolString(call->Common.dwPreferredProtocols),
1411
0
             call->Common.dwPreferredProtocols);
1412
0
  WLog_Print(log, g_LogLevel, "}");
1413
0
}
1414
1415
static void smartcard_trace_connect_w_call(wLog* log, const ConnectW_Call* call)
1416
0
{
1417
0
  WINPR_ASSERT(call);
1418
0
  char szReaderA[1024] = WINPR_C_ARRAY_INIT;
1419
1420
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1421
0
    return;
1422
1423
0
  if (call->szReader)
1424
0
    (void)ConvertWCharToUtf8(call->szReader, szReaderA, ARRAYSIZE(szReaderA));
1425
0
  WLog_Print(log, g_LogLevel, "ConnectW_Call {");
1426
0
  smartcard_log_context(log, &call->Common.handles.hContext);
1427
1428
0
  WLog_Print(log, g_LogLevel,
1429
0
             "szReader: %s dwShareMode: %s (0x%08" PRIX32
1430
0
             ") dwPreferredProtocols: %s (0x%08" PRIX32 ")",
1431
0
             szReaderA, SCardGetShareModeString(call->Common.dwShareMode),
1432
0
             call->Common.dwShareMode, SCardGetProtocolString(call->Common.dwPreferredProtocols),
1433
0
             call->Common.dwPreferredProtocols);
1434
0
  WLog_Print(log, g_LogLevel, "}");
1435
0
}
1436
1437
static void smartcard_trace_hcard_and_disposition_call(wLog* log,
1438
                                                       const HCardAndDisposition_Call* call,
1439
                                                       const char* name)
1440
0
{
1441
0
  WINPR_ASSERT(call);
1442
1443
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1444
0
    return;
1445
1446
0
  WLog_Print(log, g_LogLevel, "%s_Call {", name);
1447
0
  smartcard_log_context(log, &call->handles.hContext);
1448
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1449
1450
0
  WLog_Print(log, g_LogLevel, "dwDisposition: %s (0x%08" PRIX32 ")",
1451
0
             SCardGetDispositionString(call->dwDisposition), call->dwDisposition);
1452
0
  WLog_Print(log, g_LogLevel, "}");
1453
0
}
1454
1455
static void smartcard_trace_establish_context_call(wLog* log, const EstablishContext_Call* call)
1456
0
{
1457
0
  WINPR_ASSERT(call);
1458
1459
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1460
0
    return;
1461
1462
0
  WLog_Print(log, g_LogLevel, "EstablishContext_Call {");
1463
0
  WLog_Print(log, g_LogLevel, "dwScope: %s (0x%08" PRIX32 ")", SCardGetScopeString(call->dwScope),
1464
0
             call->dwScope);
1465
0
  WLog_Print(log, g_LogLevel, "}");
1466
0
}
1467
1468
static void smartcard_trace_establish_context_return(wLog* log, const EstablishContext_Return* ret)
1469
0
{
1470
0
  WINPR_ASSERT(ret);
1471
1472
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1473
0
    return;
1474
1475
0
  WLog_Print(log, g_LogLevel, "EstablishContext_Return {");
1476
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1477
0
             SCardGetErrorString(ret->ReturnCode),
1478
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1479
0
  smartcard_log_context(log, &ret->hContext);
1480
1481
0
  WLog_Print(log, g_LogLevel, "}");
1482
0
}
1483
1484
void smartcard_trace_long_return(const Long_Return* ret, const char* name)
1485
0
{
1486
0
  wLog* log = scard_log();
1487
0
  smartcard_trace_long_return_int(log, ret, name);
1488
0
}
1489
1490
void smartcard_trace_long_return_int(wLog* log, const Long_Return* ret, const char* name)
1491
0
{
1492
0
  WINPR_ASSERT(ret);
1493
1494
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1495
0
    return;
1496
1497
0
  WLog_Print(log, g_LogLevel, "%s_Return {", name);
1498
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1499
0
             SCardGetErrorString(ret->ReturnCode),
1500
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1501
0
  WLog_Print(log, g_LogLevel, "}");
1502
0
}
1503
1504
static void smartcard_trace_connect_return(wLog* log, const Connect_Return* ret)
1505
0
{
1506
0
  WINPR_ASSERT(ret);
1507
1508
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1509
0
    return;
1510
1511
0
  WLog_Print(log, g_LogLevel, "Connect_Return {");
1512
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1513
0
             SCardGetErrorString(ret->ReturnCode),
1514
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1515
0
  smartcard_log_context(log, &ret->hContext);
1516
0
  smartcard_log_redir_handle(log, &ret->hCard);
1517
1518
0
  WLog_Print(log, g_LogLevel, "  dwActiveProtocol: %s (0x%08" PRIX32 ")",
1519
0
             SCardGetProtocolString(ret->dwActiveProtocol), ret->dwActiveProtocol);
1520
0
  WLog_Print(log, g_LogLevel, "}");
1521
0
}
1522
1523
static void smartcard_trace_reconnect_call(wLog* log, const Reconnect_Call* call)
1524
0
{
1525
0
  WINPR_ASSERT(call);
1526
1527
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1528
0
    return;
1529
1530
0
  WLog_Print(log, g_LogLevel, "Reconnect_Call {");
1531
0
  smartcard_log_context(log, &call->handles.hContext);
1532
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1533
1534
0
  WLog_Print(log, g_LogLevel,
1535
0
             "dwShareMode: %s (0x%08" PRIX32 ") dwPreferredProtocols: %s (0x%08" PRIX32
1536
0
             ") dwInitialization: %s (0x%08" PRIX32 ")",
1537
0
             SCardGetShareModeString(call->dwShareMode), call->dwShareMode,
1538
0
             SCardGetProtocolString(call->dwPreferredProtocols), call->dwPreferredProtocols,
1539
0
             SCardGetDispositionString(call->dwInitialization), call->dwInitialization);
1540
0
  WLog_Print(log, g_LogLevel, "}");
1541
0
}
1542
1543
static void smartcard_trace_device_type_id_return(wLog* log, const GetDeviceTypeId_Return* ret)
1544
0
{
1545
0
  WINPR_ASSERT(ret);
1546
1547
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1548
0
    return;
1549
1550
0
  WLog_Print(log, g_LogLevel, "GetDeviceTypeId_Return {");
1551
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1552
0
             SCardGetErrorString(ret->ReturnCode),
1553
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1554
0
  WLog_Print(log, g_LogLevel, "  dwDeviceId=%08" PRIx32, ret->dwDeviceId);
1555
1556
0
  WLog_Print(log, g_LogLevel, "}");
1557
0
}
1558
1559
static LONG smartcard_unpack_common_context_and_string_a(wLog* log, wStream* s,
1560
                                                         REDIR_SCARDCONTEXT* phContext,
1561
                                                         CHAR** pszReaderName)
1562
0
{
1563
0
  UINT32 index = 0;
1564
0
  UINT32 pbContextNdrPtr = 0;
1565
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, phContext, &index, &pbContextNdrPtr);
1566
0
  if (status != SCARD_S_SUCCESS)
1567
0
    return status;
1568
1569
0
  if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
1570
0
    return ERROR_INVALID_DATA;
1571
1572
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, phContext);
1573
0
  if (status != SCARD_S_SUCCESS)
1574
0
    return status;
1575
1576
0
  status = smartcard_ndr_read_a(log, s, pszReaderName, NDR_PTR_FULL);
1577
0
  if (status != SCARD_S_SUCCESS)
1578
0
    return status;
1579
1580
0
  smartcard_trace_context_and_string_call_a(log, __func__, phContext, *pszReaderName);
1581
0
  return SCARD_S_SUCCESS;
1582
0
}
1583
1584
static LONG smartcard_unpack_common_context_and_string_w(wLog* log, wStream* s,
1585
                                                         REDIR_SCARDCONTEXT* phContext,
1586
                                                         WCHAR** pszReaderName)
1587
0
{
1588
0
  UINT32 index = 0;
1589
0
  UINT32 pbContextNdrPtr = 0;
1590
1591
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, phContext, &index, &pbContextNdrPtr);
1592
0
  if (status != SCARD_S_SUCCESS)
1593
0
    return status;
1594
1595
0
  if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
1596
0
    return ERROR_INVALID_DATA;
1597
1598
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, phContext);
1599
0
  if (status != SCARD_S_SUCCESS)
1600
0
    return status;
1601
1602
0
  status = smartcard_ndr_read_w(log, s, pszReaderName, NDR_PTR_FULL);
1603
0
  if (status != SCARD_S_SUCCESS)
1604
0
    return status;
1605
1606
0
  smartcard_trace_context_and_string_call_w(log, __func__, phContext, *pszReaderName);
1607
0
  return SCARD_S_SUCCESS;
1608
0
}
1609
1610
LONG smartcard_unpack_common_type_header(wStream* s)
1611
0
{
1612
0
  wLog* log = scard_log();
1613
0
  UINT8 version = 0;
1614
0
  UINT32 filler = 0;
1615
0
  UINT8 endianness = 0;
1616
0
  UINT16 commonHeaderLength = 0;
1617
1618
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
1619
0
    return STATUS_BUFFER_TOO_SMALL;
1620
1621
  /* Process CommonTypeHeader */
1622
0
  Stream_Read_UINT8(s, version);             /* Version (1 byte) */
1623
0
  Stream_Read_UINT8(s, endianness);          /* Endianness (1 byte) */
1624
0
  Stream_Read_UINT16(s, commonHeaderLength); /* CommonHeaderLength (2 bytes) */
1625
0
  Stream_Read_UINT32(s, filler);             /* Filler (4 bytes), should be 0xCCCCCCCC */
1626
1627
0
  if (version != 1)
1628
0
  {
1629
0
    WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader Version %" PRIu8 "", version);
1630
0
    return STATUS_INVALID_PARAMETER;
1631
0
  }
1632
1633
0
  if (endianness != 0x10)
1634
0
  {
1635
0
    WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader Endianness %" PRIu8 "",
1636
0
               endianness);
1637
0
    return STATUS_INVALID_PARAMETER;
1638
0
  }
1639
1640
0
  if (commonHeaderLength != 8)
1641
0
  {
1642
0
    WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader CommonHeaderLength %" PRIu16 "",
1643
0
               commonHeaderLength);
1644
0
    return STATUS_INVALID_PARAMETER;
1645
0
  }
1646
1647
0
  if (filler != 0xCCCCCCCC)
1648
0
  {
1649
0
    WLog_Print(log, WLOG_WARN, "Unexpected CommonTypeHeader Filler 0x%08" PRIX32 "", filler);
1650
0
    return STATUS_INVALID_PARAMETER;
1651
0
  }
1652
1653
0
  return SCARD_S_SUCCESS;
1654
0
}
1655
1656
void smartcard_pack_common_type_header(wStream* s)
1657
0
{
1658
0
  Stream_Write_UINT8(s, 1);           /* Version (1 byte) */
1659
0
  Stream_Write_UINT8(s, 0x10);        /* Endianness (1 byte) */
1660
0
  Stream_Write_UINT16(s, 8);          /* CommonHeaderLength (2 bytes) */
1661
0
  Stream_Write_UINT32(s, 0xCCCCCCCC); /* Filler (4 bytes), should be 0xCCCCCCCC */
1662
0
}
1663
1664
LONG smartcard_unpack_private_type_header(wStream* s)
1665
0
{
1666
0
  wLog* log = scard_log();
1667
0
  UINT32 filler = 0;
1668
0
  UINT32 objectBufferLength = 0;
1669
1670
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
1671
0
    return STATUS_BUFFER_TOO_SMALL;
1672
1673
0
  Stream_Read_UINT32(s, objectBufferLength); /* ObjectBufferLength (4 bytes) */
1674
0
  Stream_Read_UINT32(s, filler);             /* Filler (4 bytes), should be 0x00000000 */
1675
1676
0
  if (filler != 0x00000000)
1677
0
  {
1678
0
    WLog_Print(log, WLOG_WARN, "Unexpected PrivateTypeHeader Filler 0x%08" PRIX32 "", filler);
1679
0
    return STATUS_INVALID_PARAMETER;
1680
0
  }
1681
1682
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, objectBufferLength))
1683
0
    return STATUS_INVALID_PARAMETER;
1684
1685
0
  return SCARD_S_SUCCESS;
1686
0
}
1687
1688
void smartcard_pack_private_type_header(wStream* s, UINT32 objectBufferLength)
1689
0
{
1690
0
  Stream_Write_UINT32(s, objectBufferLength); /* ObjectBufferLength (4 bytes) */
1691
0
  Stream_Write_UINT32(s, 0x00000000);         /* Filler (4 bytes), should be 0x00000000 */
1692
0
}
1693
1694
LONG smartcard_unpack_read_size_align(wStream* s, size_t size, UINT32 alignment)
1695
0
{
1696
0
  const size_t padsize = (size + alignment - 1) & ~(alignment - 1);
1697
0
  const size_t pad = padsize - size;
1698
1699
0
  if (pad > 0)
1700
0
  {
1701
0
    if (!Stream_SafeSeek(s, pad))
1702
0
      return -1;
1703
0
  }
1704
1705
0
  return (LONG)pad;
1706
0
}
1707
1708
LONG smartcard_pack_write_size_align(wStream* s, size_t size, UINT32 alignment)
1709
0
{
1710
0
  const size_t padsize = (size + alignment - 1) & ~(alignment - 1);
1711
0
  const size_t pad = padsize - size;
1712
1713
0
  if (pad)
1714
0
  {
1715
0
    if (!Stream_EnsureRemainingCapacity(s, pad))
1716
0
    {
1717
0
      wLog* log = scard_log();
1718
0
      WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
1719
0
      return SCARD_F_INTERNAL_ERROR;
1720
0
    }
1721
1722
0
    Stream_Zero(s, pad);
1723
0
  }
1724
1725
0
  return SCARD_S_SUCCESS;
1726
0
}
1727
1728
SCARDCONTEXT smartcard_scard_context_native_from_redir(REDIR_SCARDCONTEXT* context)
1729
0
{
1730
0
  SCARDCONTEXT hContext = WINPR_C_ARRAY_INIT;
1731
1732
0
  WINPR_ASSERT(context);
1733
0
  if ((context->cbContext != sizeof(ULONG_PTR)) && (context->cbContext != 0))
1734
0
  {
1735
0
    wLog* log = scard_log();
1736
0
    WLog_Print(log, WLOG_WARN,
1737
0
               "REDIR_SCARDCONTEXT does not match native size: Actual: %" PRIu32
1738
0
               ", Expected: %" PRIuz "",
1739
0
               context->cbContext, sizeof(ULONG_PTR));
1740
0
    return 0;
1741
0
  }
1742
1743
0
  if (context->cbContext)
1744
0
    CopyMemory(&hContext, &(context->pbContext), context->cbContext);
1745
1746
0
  return hContext;
1747
0
}
1748
1749
void smartcard_scard_context_native_to_redir(REDIR_SCARDCONTEXT* context, SCARDCONTEXT hContext)
1750
0
{
1751
0
  WINPR_ASSERT(context);
1752
0
  ZeroMemory(context, sizeof(REDIR_SCARDCONTEXT));
1753
0
  context->cbContext = sizeof(ULONG_PTR);
1754
0
  CopyMemory(&(context->pbContext), &hContext, context->cbContext);
1755
0
}
1756
1757
SCARDHANDLE smartcard_scard_handle_native_from_redir(REDIR_SCARDHANDLE* handle)
1758
0
{
1759
0
  SCARDHANDLE hCard = 0;
1760
1761
0
  WINPR_ASSERT(handle);
1762
0
  if (handle->cbHandle == 0)
1763
0
    return hCard;
1764
1765
0
  if (handle->cbHandle != sizeof(ULONG_PTR))
1766
0
  {
1767
0
    wLog* log = scard_log();
1768
0
    WLog_Print(log, WLOG_WARN,
1769
0
               "REDIR_SCARDHANDLE does not match native size: Actual: %" PRIu32
1770
0
               ", Expected: %" PRIuz "",
1771
0
               handle->cbHandle, sizeof(ULONG_PTR));
1772
0
    return 0;
1773
0
  }
1774
1775
0
  if (handle->cbHandle)
1776
0
    CopyMemory(&hCard, &(handle->pbHandle), handle->cbHandle);
1777
1778
0
  return hCard;
1779
0
}
1780
1781
void smartcard_scard_handle_native_to_redir(REDIR_SCARDHANDLE* handle, SCARDHANDLE hCard)
1782
0
{
1783
0
  WINPR_ASSERT(handle);
1784
0
  ZeroMemory(handle, sizeof(REDIR_SCARDHANDLE));
1785
0
  handle->cbHandle = sizeof(ULONG_PTR);
1786
0
  CopyMemory(&(handle->pbHandle), &hCard, handle->cbHandle);
1787
0
}
1788
1789
#define smartcard_context_supported(log, size) \
1790
0
  smartcard_context_supported_((log), (size), __FILE__, __func__, __LINE__)
1791
static LONG smartcard_context_supported_(wLog* log, uint32_t size, const char* file,
1792
                                         const char* fkt, size_t line)
1793
0
{
1794
0
  switch (size)
1795
0
  {
1796
0
    case 0:
1797
0
    case 4:
1798
0
    case 8:
1799
0
      return SCARD_S_SUCCESS;
1800
0
    default:
1801
0
    {
1802
0
      const uint32_t level = WLOG_WARN;
1803
0
      if (WLog_IsLevelActive(log, level))
1804
0
      {
1805
0
        WLog_PrintTextMessage(log, level, line, file, fkt,
1806
0
                              "REDIR_SCARDCONTEXT length is not 0, 4 or 8: %" PRIu32 "",
1807
0
                              size);
1808
0
      }
1809
0
      return STATUS_INVALID_PARAMETER;
1810
0
    }
1811
0
  }
1812
0
}
1813
1814
LONG smartcard_unpack_redir_scard_context_(wLog* log, wStream* s, REDIR_SCARDCONTEXT* context,
1815
                                           UINT32* index, UINT32* ppbContextNdrPtr,
1816
                                           const char* file, const char* function, size_t line)
1817
0
{
1818
0
  UINT32 pbContextNdrPtr = 0;
1819
1820
0
  WINPR_UNUSED(file);
1821
0
  WINPR_ASSERT(context);
1822
1823
0
  ZeroMemory(context, sizeof(REDIR_SCARDCONTEXT));
1824
1825
0
  if (!Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, 4, 1, "%s(%s:%" PRIuz ")", file,
1826
0
                                              function, line))
1827
0
    return STATUS_BUFFER_TOO_SMALL;
1828
1829
0
  const LONG status = smartcard_context_supported_(log, context->cbContext, file, function, line);
1830
0
  if (status != SCARD_S_SUCCESS)
1831
0
    return status;
1832
1833
0
  Stream_Read_UINT32(s, context->cbContext); /* cbContext (4 bytes) */
1834
1835
0
  if (!smartcard_ndr_pointer_read_(log, s, index, &pbContextNdrPtr, file, function, line))
1836
0
    return ERROR_INVALID_DATA;
1837
1838
0
  if (((context->cbContext == 0) && pbContextNdrPtr) ||
1839
0
      ((context->cbContext != 0) && !pbContextNdrPtr))
1840
0
  {
1841
0
    WLog_Print(log, WLOG_WARN,
1842
0
               "REDIR_SCARDCONTEXT cbContext (%" PRIu32 ") pbContextNdrPtr (%" PRIu32
1843
0
               ") inconsistency",
1844
0
               context->cbContext, pbContextNdrPtr);
1845
0
    return STATUS_INVALID_PARAMETER;
1846
0
  }
1847
1848
0
  if (!Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, context->cbContext, 1,
1849
0
                                              "%s(%s:%" PRIuz ")", file, function, line))
1850
0
    return STATUS_INVALID_PARAMETER;
1851
1852
0
  *ppbContextNdrPtr = pbContextNdrPtr;
1853
0
  return SCARD_S_SUCCESS;
1854
0
}
1855
1856
LONG smartcard_pack_redir_scard_context(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1857
                                        const REDIR_SCARDCONTEXT* context, DWORD* index)
1858
0
{
1859
0
  const UINT32 pbContextNdrPtr = 0x00020000 + *index * 4;
1860
1861
0
  WINPR_ASSERT(context);
1862
0
  if (context->cbContext != 0)
1863
0
  {
1864
0
    Stream_Write_UINT32(s, context->cbContext); /* cbContext (4 bytes) */
1865
0
    Stream_Write_UINT32(s, pbContextNdrPtr);    /* pbContextNdrPtr (4 bytes) */
1866
0
    *index = *index + 1;
1867
0
  }
1868
0
  else
1869
0
    Stream_Zero(s, 8);
1870
1871
0
  return SCARD_S_SUCCESS;
1872
0
}
1873
1874
LONG smartcard_unpack_redir_scard_context_ref(wLog* log, wStream* s,
1875
                                              WINPR_ATTR_UNUSED UINT32 pbContextNdrPtr,
1876
                                              REDIR_SCARDCONTEXT* context)
1877
0
{
1878
0
  UINT32 length = 0;
1879
1880
0
  WINPR_ASSERT(context);
1881
0
  if (context->cbContext == 0)
1882
0
    return SCARD_S_SUCCESS;
1883
1884
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
1885
0
    return STATUS_BUFFER_TOO_SMALL;
1886
1887
0
  Stream_Read_UINT32(s, length); /* Length (4 bytes) */
1888
1889
0
  if (length != context->cbContext)
1890
0
  {
1891
0
    WLog_Print(log, WLOG_WARN,
1892
0
               "REDIR_SCARDCONTEXT length (%" PRIu32 ") cbContext (%" PRIu32 ") mismatch",
1893
0
               length, context->cbContext);
1894
0
    return STATUS_INVALID_PARAMETER;
1895
0
  }
1896
1897
0
  const LONG status = smartcard_context_supported(log, context->cbContext);
1898
0
  if (status != SCARD_S_SUCCESS)
1899
0
    return status;
1900
1901
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, context->cbContext))
1902
0
    return STATUS_BUFFER_TOO_SMALL;
1903
1904
0
  if (context->cbContext)
1905
0
    Stream_Read(s, &(context->pbContext), context->cbContext);
1906
0
  else
1907
0
    ZeroMemory(&(context->pbContext), sizeof(context->pbContext));
1908
1909
0
  return SCARD_S_SUCCESS;
1910
0
}
1911
1912
LONG smartcard_pack_redir_scard_context_ref(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1913
                                            const REDIR_SCARDCONTEXT* context)
1914
0
{
1915
0
  WINPR_ASSERT(context);
1916
0
  Stream_Write_UINT32(s, context->cbContext); /* Length (4 bytes) */
1917
1918
0
  if (context->cbContext)
1919
0
  {
1920
0
    Stream_Write(s, &(context->pbContext), context->cbContext);
1921
0
  }
1922
1923
0
  return SCARD_S_SUCCESS;
1924
0
}
1925
1926
LONG smartcard_unpack_redir_scard_handle_(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle,
1927
                                          UINT32* index, const char* file, const char* function,
1928
                                          size_t line)
1929
0
{
1930
0
  WINPR_ASSERT(handle);
1931
0
  ZeroMemory(handle, sizeof(REDIR_SCARDHANDLE));
1932
1933
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
1934
0
    return STATUS_BUFFER_TOO_SMALL;
1935
1936
0
  Stream_Read_UINT32(s, handle->cbHandle); /* Length (4 bytes) */
1937
1938
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, handle->cbHandle))
1939
0
    return STATUS_BUFFER_TOO_SMALL;
1940
1941
0
  if (!smartcard_ndr_pointer_read_(log, s, index, nullptr, file, function, line))
1942
0
    return ERROR_INVALID_DATA;
1943
1944
0
  return SCARD_S_SUCCESS;
1945
0
}
1946
1947
LONG smartcard_pack_redir_scard_handle(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1948
                                       const REDIR_SCARDHANDLE* handle, DWORD* index)
1949
0
{
1950
0
  const UINT32 pbContextNdrPtr = 0x00020000 + *index * 4;
1951
1952
0
  WINPR_ASSERT(handle);
1953
0
  if (handle->cbHandle != 0)
1954
0
  {
1955
0
    Stream_Write_UINT32(s, handle->cbHandle); /* cbContext (4 bytes) */
1956
0
    Stream_Write_UINT32(s, pbContextNdrPtr);  /* pbContextNdrPtr (4 bytes) */
1957
0
    *index = *index + 1;
1958
0
  }
1959
0
  else
1960
0
    Stream_Zero(s, 8);
1961
0
  return SCARD_S_SUCCESS;
1962
0
}
1963
1964
LONG smartcard_unpack_redir_scard_handle_ref(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle)
1965
0
{
1966
0
  UINT32 length = 0;
1967
1968
0
  WINPR_ASSERT(handle);
1969
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
1970
0
    return STATUS_BUFFER_TOO_SMALL;
1971
1972
0
  Stream_Read_UINT32(s, length); /* Length (4 bytes) */
1973
1974
0
  if (length != handle->cbHandle)
1975
0
  {
1976
0
    WLog_Print(log, WLOG_WARN,
1977
0
               "REDIR_SCARDHANDLE length (%" PRIu32 ") cbHandle (%" PRIu32 ") mismatch", length,
1978
0
               handle->cbHandle);
1979
0
    return STATUS_INVALID_PARAMETER;
1980
0
  }
1981
1982
0
  if ((handle->cbHandle != 4) && (handle->cbHandle != 8))
1983
0
  {
1984
0
    WLog_Print(log, WLOG_WARN, "REDIR_SCARDHANDLE length is not 4 or 8: %" PRIu32 "",
1985
0
               handle->cbHandle);
1986
0
    return STATUS_INVALID_PARAMETER;
1987
0
  }
1988
1989
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, handle->cbHandle))
1990
0
    return STATUS_BUFFER_TOO_SMALL;
1991
1992
0
  if (handle->cbHandle)
1993
0
    Stream_Read(s, &(handle->pbHandle), handle->cbHandle);
1994
1995
0
  return SCARD_S_SUCCESS;
1996
0
}
1997
1998
LONG smartcard_pack_redir_scard_handle_ref(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1999
                                           const REDIR_SCARDHANDLE* handle)
2000
0
{
2001
0
  WINPR_ASSERT(handle);
2002
0
  Stream_Write_UINT32(s, handle->cbHandle); /* Length (4 bytes) */
2003
2004
0
  if (handle->cbHandle)
2005
0
    Stream_Write(s, &(handle->pbHandle), handle->cbHandle);
2006
2007
0
  return SCARD_S_SUCCESS;
2008
0
}
2009
2010
LONG smartcard_unpack_establish_context_call(wStream* s, EstablishContext_Call* call)
2011
0
{
2012
0
  WINPR_ASSERT(call);
2013
0
  wLog* log = scard_log();
2014
2015
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2016
0
    return STATUS_BUFFER_TOO_SMALL;
2017
2018
0
  Stream_Read_UINT32(s, call->dwScope); /* dwScope (4 bytes) */
2019
0
  smartcard_trace_establish_context_call(log, call);
2020
0
  return SCARD_S_SUCCESS;
2021
0
}
2022
2023
LONG smartcard_pack_establish_context_return(wStream* s, const EstablishContext_Return* ret)
2024
0
{
2025
0
  WINPR_ASSERT(ret);
2026
0
  wLog* log = scard_log();
2027
0
  LONG status = 0;
2028
0
  DWORD index = 0;
2029
2030
0
  smartcard_trace_establish_context_return(log, ret);
2031
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
2032
0
    return ret->ReturnCode;
2033
2034
0
  status = smartcard_pack_redir_scard_context(log, s, &(ret->hContext), &index);
2035
0
  if (status != SCARD_S_SUCCESS)
2036
0
    return status;
2037
2038
0
  return smartcard_pack_redir_scard_context_ref(log, s, &(ret->hContext));
2039
0
}
2040
2041
LONG smartcard_unpack_context_call(wStream* s, Context_Call* call, const char* name)
2042
0
{
2043
0
  UINT32 index = 0;
2044
0
  UINT32 pbContextNdrPtr = 0;
2045
0
  wLog* log = scard_log();
2046
2047
0
  WINPR_ASSERT(call);
2048
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2049
0
                                                     &pbContextNdrPtr);
2050
0
  if (status != SCARD_S_SUCCESS)
2051
0
    return status;
2052
2053
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2054
0
                                                    &(call->handles.hContext));
2055
0
  if (status != SCARD_S_SUCCESS)
2056
0
    WLog_Print(log, WLOG_ERROR,
2057
0
               "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2058
0
               status);
2059
2060
0
  smartcard_trace_context_call(log, call, name);
2061
0
  return status;
2062
0
}
2063
2064
LONG smartcard_unpack_list_reader_groups_call(wStream* s, ListReaderGroups_Call* call, BOOL unicode)
2065
0
{
2066
0
  UINT32 index = 0;
2067
0
  UINT32 pbContextNdrPtr = 0;
2068
0
  wLog* log = scard_log();
2069
2070
0
  WINPR_ASSERT(call);
2071
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2072
0
                                                     &pbContextNdrPtr);
2073
2074
0
  if (status != SCARD_S_SUCCESS)
2075
0
    return status;
2076
2077
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2078
0
    return STATUS_BUFFER_TOO_SMALL;
2079
2080
0
  Stream_Read_INT32(s, call->fmszGroupsIsNULL); /* fmszGroupsIsNULL (4 bytes) */
2081
0
  Stream_Read_UINT32(s, call->cchGroups);       /* cchGroups (4 bytes) */
2082
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2083
0
                                                    &(call->handles.hContext));
2084
2085
0
  if (status != SCARD_S_SUCCESS)
2086
0
    return status;
2087
2088
0
  smartcard_trace_list_reader_groups_call(log, call, unicode);
2089
0
  return SCARD_S_SUCCESS;
2090
0
}
2091
2092
LONG smartcard_pack_list_reader_groups_return(wStream* s, const ListReaderGroups_Return* ret,
2093
                                              BOOL unicode)
2094
0
{
2095
0
  WINPR_ASSERT(ret);
2096
0
  wLog* log = scard_log();
2097
0
  LONG status = 0;
2098
0
  DWORD cBytes = ret->cBytes;
2099
0
  UINT32 index = 0;
2100
2101
0
  smartcard_trace_list_reader_groups_return(log, ret, unicode);
2102
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
2103
0
    cBytes = 0;
2104
0
  if (cBytes == SCARD_AUTOALLOCATE)
2105
0
    cBytes = 0;
2106
2107
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
2108
0
    return SCARD_E_NO_MEMORY;
2109
2110
0
  Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
2111
0
  if (!smartcard_ndr_pointer_write(s, &index, cBytes))
2112
0
    return SCARD_E_NO_MEMORY;
2113
2114
0
  status = smartcard_ndr_write(s, ret->msz, cBytes, 1, NDR_PTR_SIMPLE);
2115
0
  if (status != SCARD_S_SUCCESS)
2116
0
    return status;
2117
0
  return ret->ReturnCode;
2118
0
}
2119
2120
LONG smartcard_unpack_list_readers_call(wStream* s, ListReaders_Call* call, BOOL unicode)
2121
0
{
2122
0
  UINT32 index = 0;
2123
0
  UINT32 mszGroupsNdrPtr = 0;
2124
0
  UINT32 pbContextNdrPtr = 0;
2125
0
  wLog* log = scard_log();
2126
2127
0
  WINPR_ASSERT(call);
2128
0
  call->mszGroups = nullptr;
2129
2130
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2131
0
                                                     &pbContextNdrPtr);
2132
0
  if (status != SCARD_S_SUCCESS)
2133
0
    return status;
2134
2135
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2136
0
    return STATUS_BUFFER_TOO_SMALL;
2137
2138
0
  Stream_Read_UINT32(s, call->cBytes); /* cBytes (4 bytes) */
2139
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &mszGroupsNdrPtr))
2140
0
    return ERROR_INVALID_DATA;
2141
2142
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2143
0
    return STATUS_BUFFER_TOO_SMALL;
2144
0
  Stream_Read_INT32(s, call->fmszReadersIsNULL); /* fmszReadersIsNULL (4 bytes) */
2145
0
  Stream_Read_UINT32(s, call->cchReaders);       /* cchReaders (4 bytes) */
2146
2147
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2148
0
                                                    &(call->handles.hContext));
2149
0
  if (status != SCARD_S_SUCCESS)
2150
0
    return status;
2151
2152
0
  if (mszGroupsNdrPtr)
2153
0
  {
2154
0
    status = smartcard_ndr_read(log, s, &call->mszGroups, call->cBytes, 1, NDR_PTR_SIMPLE);
2155
0
    if (status != SCARD_S_SUCCESS)
2156
0
      return status;
2157
0
  }
2158
2159
0
  smartcard_trace_list_readers_call(log, call, unicode);
2160
0
  return SCARD_S_SUCCESS;
2161
0
}
2162
2163
LONG smartcard_pack_list_readers_return(wStream* s, const ListReaders_Return* ret, BOOL unicode)
2164
0
{
2165
0
  WINPR_ASSERT(ret);
2166
0
  wLog* log = scard_log();
2167
0
  LONG status = 0;
2168
0
  UINT32 index = 0;
2169
0
  UINT32 size = ret->cBytes;
2170
2171
0
  smartcard_trace_list_readers_return(log, ret, unicode);
2172
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
2173
0
    size = 0;
2174
2175
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
2176
0
  {
2177
0
    WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
2178
0
    return SCARD_F_INTERNAL_ERROR;
2179
0
  }
2180
2181
0
  Stream_Write_UINT32(s, size); /* cBytes (4 bytes) */
2182
0
  if (!smartcard_ndr_pointer_write(s, &index, size))
2183
0
    return SCARD_E_NO_MEMORY;
2184
2185
0
  status = smartcard_ndr_write(s, ret->msz, size, 1, NDR_PTR_SIMPLE);
2186
0
  if (status != SCARD_S_SUCCESS)
2187
0
    return status;
2188
0
  return ret->ReturnCode;
2189
0
}
2190
2191
static LONG smartcard_unpack_connect_common(wLog* log, wStream* s, Connect_Common_Call* common,
2192
                                            UINT32* index, UINT32* ppbContextNdrPtr)
2193
0
{
2194
0
  WINPR_ASSERT(common);
2195
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(common->handles.hContext), index,
2196
0
                                                     ppbContextNdrPtr);
2197
0
  if (status != SCARD_S_SUCCESS)
2198
0
    return status;
2199
2200
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2201
0
    return STATUS_BUFFER_TOO_SMALL;
2202
2203
0
  Stream_Read_UINT32(s, common->dwShareMode);          /* dwShareMode (4 bytes) */
2204
0
  Stream_Read_UINT32(s, common->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
2205
0
  return SCARD_S_SUCCESS;
2206
0
}
2207
2208
LONG smartcard_unpack_connect_a_call(wStream* s, ConnectA_Call* call)
2209
0
{
2210
0
  LONG status = 0;
2211
0
  UINT32 index = 0;
2212
0
  UINT32 pbContextNdrPtr = 0;
2213
2214
0
  WINPR_ASSERT(call);
2215
0
  wLog* log = scard_log();
2216
2217
0
  call->szReader = nullptr;
2218
2219
0
  if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
2220
0
    return ERROR_INVALID_DATA;
2221
2222
0
  status = smartcard_unpack_connect_common(log, s, &(call->Common), &index, &pbContextNdrPtr);
2223
0
  if (status != SCARD_S_SUCCESS)
2224
0
  {
2225
0
    WLog_Print(log, WLOG_ERROR, "smartcard_unpack_connect_common failed with error %" PRId32 "",
2226
0
               status);
2227
0
    return status;
2228
0
  }
2229
2230
0
  status = smartcard_ndr_read_a(log, s, &call->szReader, NDR_PTR_FULL);
2231
0
  if (status != SCARD_S_SUCCESS)
2232
0
    return status;
2233
2234
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2235
0
                                                    &(call->Common.handles.hContext));
2236
0
  if (status != SCARD_S_SUCCESS)
2237
0
    WLog_Print(log, WLOG_ERROR,
2238
0
               "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2239
0
               status);
2240
2241
0
  smartcard_trace_connect_a_call(log, call);
2242
0
  return status;
2243
0
}
2244
2245
LONG smartcard_unpack_connect_w_call(wStream* s, ConnectW_Call* call)
2246
0
{
2247
0
  LONG status = 0;
2248
0
  UINT32 index = 0;
2249
0
  UINT32 pbContextNdrPtr = 0;
2250
2251
0
  WINPR_ASSERT(call);
2252
0
  wLog* log = scard_log();
2253
0
  call->szReader = nullptr;
2254
2255
0
  if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
2256
0
    return ERROR_INVALID_DATA;
2257
2258
0
  status = smartcard_unpack_connect_common(log, s, &(call->Common), &index, &pbContextNdrPtr);
2259
0
  if (status != SCARD_S_SUCCESS)
2260
0
  {
2261
0
    WLog_Print(log, WLOG_ERROR, "smartcard_unpack_connect_common failed with error %" PRId32 "",
2262
0
               status);
2263
0
    return status;
2264
0
  }
2265
2266
0
  status = smartcard_ndr_read_w(log, s, &call->szReader, NDR_PTR_FULL);
2267
0
  if (status != SCARD_S_SUCCESS)
2268
0
    return status;
2269
2270
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2271
0
                                                    &(call->Common.handles.hContext));
2272
0
  if (status != SCARD_S_SUCCESS)
2273
0
    WLog_Print(log, WLOG_ERROR,
2274
0
               "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2275
0
               status);
2276
2277
0
  smartcard_trace_connect_w_call(log, call);
2278
0
  return status;
2279
0
}
2280
2281
LONG smartcard_pack_connect_return(wStream* s, const Connect_Return* ret)
2282
0
{
2283
0
  LONG status = 0;
2284
0
  DWORD index = 0;
2285
2286
0
  WINPR_ASSERT(ret);
2287
0
  wLog* log = scard_log();
2288
0
  smartcard_trace_connect_return(log, ret);
2289
2290
0
  status = smartcard_pack_redir_scard_context(log, s, &ret->hContext, &index);
2291
0
  if (status != SCARD_S_SUCCESS)
2292
0
    return status;
2293
2294
0
  status = smartcard_pack_redir_scard_handle(log, s, &ret->hCard, &index);
2295
0
  if (status != SCARD_S_SUCCESS)
2296
0
    return status;
2297
2298
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
2299
0
    return SCARD_E_NO_MEMORY;
2300
2301
0
  Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
2302
0
  status = smartcard_pack_redir_scard_context_ref(log, s, &ret->hContext);
2303
0
  if (status != SCARD_S_SUCCESS)
2304
0
    return status;
2305
0
  return smartcard_pack_redir_scard_handle_ref(log, s, &(ret->hCard));
2306
0
}
2307
2308
LONG smartcard_unpack_reconnect_call(wStream* s, Reconnect_Call* call)
2309
0
{
2310
0
  UINT32 index = 0;
2311
0
  UINT32 pbContextNdrPtr = 0;
2312
2313
0
  WINPR_ASSERT(call);
2314
0
  wLog* log = scard_log();
2315
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2316
0
                                                     &pbContextNdrPtr);
2317
0
  if (status != SCARD_S_SUCCESS)
2318
0
    return status;
2319
2320
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2321
0
  if (status != SCARD_S_SUCCESS)
2322
0
    return status;
2323
2324
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
2325
0
    return STATUS_BUFFER_TOO_SMALL;
2326
2327
0
  Stream_Read_UINT32(s, call->dwShareMode);          /* dwShareMode (4 bytes) */
2328
0
  Stream_Read_UINT32(s, call->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
2329
0
  Stream_Read_UINT32(s, call->dwInitialization);     /* dwInitialization (4 bytes) */
2330
2331
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2332
0
                                                    &(call->handles.hContext));
2333
0
  if (status != SCARD_S_SUCCESS)
2334
0
  {
2335
0
    WLog_Print(log, WLOG_ERROR,
2336
0
               "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2337
0
               status);
2338
0
    return status;
2339
0
  }
2340
2341
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2342
0
  if (status != SCARD_S_SUCCESS)
2343
0
    WLog_Print(log, WLOG_ERROR,
2344
0
               "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status);
2345
2346
0
  smartcard_trace_reconnect_call(log, call);
2347
0
  return status;
2348
0
}
2349
2350
LONG smartcard_pack_reconnect_return(wStream* s, const Reconnect_Return* ret)
2351
0
{
2352
0
  WINPR_ASSERT(ret);
2353
0
  wLog* log = scard_log();
2354
0
  smartcard_trace_reconnect_return(log, ret);
2355
2356
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
2357
0
    return SCARD_E_NO_MEMORY;
2358
0
  Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
2359
0
  return ret->ReturnCode;
2360
0
}
2361
2362
LONG smartcard_unpack_hcard_and_disposition_call(wStream* s, HCardAndDisposition_Call* call,
2363
                                                 const char* name)
2364
0
{
2365
0
  UINT32 index = 0;
2366
0
  UINT32 pbContextNdrPtr = 0;
2367
2368
0
  WINPR_ASSERT(call);
2369
0
  wLog* log = scard_log();
2370
2371
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2372
0
                                                     &pbContextNdrPtr);
2373
0
  if (status != SCARD_S_SUCCESS)
2374
0
    return status;
2375
2376
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2377
0
  if (status != SCARD_S_SUCCESS)
2378
0
    return status;
2379
2380
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2381
0
    return STATUS_BUFFER_TOO_SMALL;
2382
2383
0
  Stream_Read_UINT32(s, call->dwDisposition); /* dwDisposition (4 bytes) */
2384
2385
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2386
0
                                                    &(call->handles.hContext));
2387
0
  if (status != SCARD_S_SUCCESS)
2388
0
    return status;
2389
2390
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2391
0
  if (status != SCARD_S_SUCCESS)
2392
0
    return status;
2393
2394
0
  smartcard_trace_hcard_and_disposition_call(log, call, name);
2395
0
  return status;
2396
0
}
2397
2398
static void smartcard_trace_get_status_change_a_call(wLog* log, const GetStatusChangeA_Call* call)
2399
0
{
2400
0
  WINPR_ASSERT(call);
2401
2402
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
2403
0
    return;
2404
2405
0
  WLog_Print(log, g_LogLevel, "GetStatusChangeA_Call {");
2406
0
  smartcard_log_context(log, &call->handles.hContext);
2407
2408
0
  WLog_Print(log, g_LogLevel, "dwTimeOut: 0x%08" PRIX32 " cReaders: %" PRIu32 "", call->dwTimeOut,
2409
0
             call->cReaders);
2410
2411
0
  dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
2412
2413
0
  WLog_Print(log, g_LogLevel, "}");
2414
0
}
2415
2416
static LONG smartcard_unpack_reader_state_a(wLog* log, wStream* s, LPSCARD_READERSTATEA* ppcReaders,
2417
                                            UINT32 cReaders, UINT32* ptrIndex)
2418
0
{
2419
0
  LONG status = SCARD_E_NO_MEMORY;
2420
2421
0
  WINPR_ASSERT(ppcReaders || (cReaders == 0));
2422
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2423
0
    return status;
2424
2425
0
  const UINT32 len = Stream_Get_UINT32(s);
2426
0
  if (len != cReaders)
2427
0
  {
2428
0
    WLog_Print(log, WLOG_ERROR, "Count mismatch when reading LPSCARD_READERSTATEA");
2429
0
    return status;
2430
0
  }
2431
2432
0
  LPSCARD_READERSTATEA rgReaderStates =
2433
0
      (LPSCARD_READERSTATEA)calloc(cReaders, sizeof(SCARD_READERSTATEA));
2434
0
  BOOL* states = calloc(cReaders, sizeof(BOOL));
2435
0
  if (!rgReaderStates || !states)
2436
0
    goto fail;
2437
0
  status = ERROR_INVALID_DATA;
2438
2439
0
  for (UINT32 index = 0; index < cReaders; index++)
2440
0
  {
2441
0
    UINT32 ptr = UINT32_MAX;
2442
0
    LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2443
2444
0
    if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 52))
2445
0
      goto fail;
2446
2447
0
    if (!smartcard_ndr_pointer_read(log, s, ptrIndex, &ptr))
2448
0
    {
2449
0
      if (ptr != 0)
2450
0
        goto fail;
2451
0
    }
2452
    /* Ignore nullptr length strings */
2453
0
    states[index] = ptr != 0;
2454
0
    Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2455
0
    Stream_Read_UINT32(s, readerState->dwEventState);   /* dwEventState (4 bytes) */
2456
0
    Stream_Read_UINT32(s, readerState->cbAtr);          /* cbAtr (4 bytes) */
2457
0
    Stream_Read(s, readerState->rgbAtr, 36);            /* rgbAtr [0..36] (36 bytes) */
2458
0
  }
2459
2460
0
  for (UINT32 index = 0; index < cReaders; index++)
2461
0
  {
2462
0
    LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2463
2464
    /* Ignore empty strings */
2465
0
    if (!states[index])
2466
0
      continue;
2467
0
    status = smartcard_ndr_read_a(log, s, &readerState->szReader, NDR_PTR_FULL);
2468
0
    if (status != SCARD_S_SUCCESS)
2469
0
      goto fail;
2470
0
  }
2471
2472
0
  *ppcReaders = rgReaderStates;
2473
0
  free(states);
2474
0
  return SCARD_S_SUCCESS;
2475
0
fail:
2476
0
  if (rgReaderStates)
2477
0
  {
2478
0
    for (UINT32 index = 0; index < cReaders; index++)
2479
0
    {
2480
0
      LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2481
0
      free(readerState->szReader);
2482
0
    }
2483
0
  }
2484
0
  free(rgReaderStates);
2485
0
  free(states);
2486
0
  return status;
2487
0
}
2488
2489
static LONG smartcard_unpack_reader_state_w(wLog* log, wStream* s, LPSCARD_READERSTATEW* ppcReaders,
2490
                                            UINT32 cReaders, UINT32* ptrIndex)
2491
0
{
2492
0
  LONG status = SCARD_E_NO_MEMORY;
2493
2494
0
  WINPR_ASSERT(ppcReaders || (cReaders == 0));
2495
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2496
0
    return status;
2497
2498
0
  const UINT32 len = Stream_Get_UINT32(s);
2499
0
  if (len != cReaders)
2500
0
  {
2501
0
    WLog_Print(log, WLOG_ERROR, "Count mismatch when reading LPSCARD_READERSTATEW");
2502
0
    return status;
2503
0
  }
2504
2505
0
  LPSCARD_READERSTATEW rgReaderStates =
2506
0
      (LPSCARD_READERSTATEW)calloc(cReaders, sizeof(SCARD_READERSTATEW));
2507
0
  BOOL* states = calloc(cReaders, sizeof(BOOL));
2508
2509
0
  if (!rgReaderStates || !states)
2510
0
    goto fail;
2511
2512
0
  status = ERROR_INVALID_DATA;
2513
0
  for (UINT32 index = 0; index < cReaders; index++)
2514
0
  {
2515
0
    UINT32 ptr = UINT32_MAX;
2516
0
    LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2517
2518
0
    if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 52))
2519
0
      goto fail;
2520
2521
0
    if (!smartcard_ndr_pointer_read(log, s, ptrIndex, &ptr))
2522
0
    {
2523
0
      if (ptr != 0)
2524
0
        goto fail;
2525
0
    }
2526
    /* Ignore nullptr length strings */
2527
0
    states[index] = ptr != 0;
2528
0
    Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2529
0
    Stream_Read_UINT32(s, readerState->dwEventState);   /* dwEventState (4 bytes) */
2530
0
    Stream_Read_UINT32(s, readerState->cbAtr);          /* cbAtr (4 bytes) */
2531
0
    Stream_Read(s, readerState->rgbAtr, 36);            /* rgbAtr [0..36] (36 bytes) */
2532
0
  }
2533
2534
0
  for (UINT32 index = 0; index < cReaders; index++)
2535
0
  {
2536
0
    LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2537
2538
    /* Skip nullptr pointers */
2539
0
    if (!states[index])
2540
0
      continue;
2541
2542
0
    status = smartcard_ndr_read_w(log, s, &readerState->szReader, NDR_PTR_FULL);
2543
0
    if (status != SCARD_S_SUCCESS)
2544
0
      goto fail;
2545
0
  }
2546
2547
0
  *ppcReaders = rgReaderStates;
2548
0
  free(states);
2549
0
  return SCARD_S_SUCCESS;
2550
0
fail:
2551
0
  if (rgReaderStates)
2552
0
  {
2553
0
    for (UINT32 index = 0; index < cReaders; index++)
2554
0
    {
2555
0
      LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2556
0
      free(readerState->szReader);
2557
0
    }
2558
0
  }
2559
0
  free(rgReaderStates);
2560
0
  free(states);
2561
0
  return status;
2562
0
}
2563
2564
/******************************************************************************/
2565
/************************************* End Trace Functions ********************/
2566
/******************************************************************************/
2567
2568
LONG smartcard_unpack_get_status_change_a_call(wStream* s, GetStatusChangeA_Call* call)
2569
0
{
2570
0
  UINT32 ndrPtr = 0;
2571
0
  UINT32 index = 0;
2572
0
  UINT32 pbContextNdrPtr = 0;
2573
2574
0
  WINPR_ASSERT(call);
2575
0
  wLog* log = scard_log();
2576
2577
0
  call->rgReaderStates = nullptr;
2578
2579
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2580
0
                                                     &pbContextNdrPtr);
2581
0
  if (status != SCARD_S_SUCCESS)
2582
0
    return status;
2583
2584
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2585
0
    return STATUS_BUFFER_TOO_SMALL;
2586
2587
0
  Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2588
0
  Stream_Read_UINT32(s, call->cReaders);  /* cReaders (4 bytes) */
2589
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
2590
0
    return ERROR_INVALID_DATA;
2591
2592
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2593
0
                                                    &(call->handles.hContext));
2594
0
  if (status != SCARD_S_SUCCESS)
2595
0
    return status;
2596
2597
0
  if (ndrPtr)
2598
0
  {
2599
0
    status =
2600
0
        smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, call->cReaders, &index);
2601
0
    if (status != SCARD_S_SUCCESS)
2602
0
      return status;
2603
0
  }
2604
0
  else
2605
0
  {
2606
0
    WLog_Print(log, WLOG_WARN, "ndrPtr=0x%08" PRIx32 ", can not read rgReaderStates", ndrPtr);
2607
0
    return SCARD_E_UNEXPECTED;
2608
0
  }
2609
2610
0
  smartcard_trace_get_status_change_a_call(log, call);
2611
0
  return SCARD_S_SUCCESS;
2612
0
}
2613
2614
LONG smartcard_unpack_get_status_change_w_call(wStream* s, GetStatusChangeW_Call* call)
2615
0
{
2616
0
  UINT32 ndrPtr = 0;
2617
0
  UINT32 index = 0;
2618
0
  UINT32 pbContextNdrPtr = 0;
2619
2620
0
  WINPR_ASSERT(call);
2621
0
  wLog* log = scard_log();
2622
0
  call->rgReaderStates = nullptr;
2623
2624
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2625
0
                                                     &pbContextNdrPtr);
2626
0
  if (status != SCARD_S_SUCCESS)
2627
0
    return status;
2628
2629
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2630
0
    return STATUS_BUFFER_TOO_SMALL;
2631
2632
0
  Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2633
0
  Stream_Read_UINT32(s, call->cReaders);  /* cReaders (4 bytes) */
2634
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
2635
0
    return ERROR_INVALID_DATA;
2636
2637
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2638
0
                                                    &(call->handles.hContext));
2639
0
  if (status != SCARD_S_SUCCESS)
2640
0
    return status;
2641
2642
0
  if (ndrPtr)
2643
0
  {
2644
0
    status =
2645
0
        smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, call->cReaders, &index);
2646
0
    if (status != SCARD_S_SUCCESS)
2647
0
      return status;
2648
0
  }
2649
0
  else
2650
0
  {
2651
0
    WLog_Print(log, WLOG_WARN, "ndrPtr=0x%08" PRIx32 ", can not read rgReaderStates", ndrPtr);
2652
0
    return SCARD_E_UNEXPECTED;
2653
0
  }
2654
2655
0
  smartcard_trace_get_status_change_w_call(log, call);
2656
0
  return SCARD_S_SUCCESS;
2657
0
}
2658
2659
LONG smartcard_pack_get_status_change_return(wStream* s, const GetStatusChange_Return* ret,
2660
                                             BOOL unicode)
2661
0
{
2662
0
  WINPR_ASSERT(ret);
2663
0
  wLog* log = scard_log();
2664
2665
0
  LONG status = 0;
2666
0
  DWORD cReaders = ret->cReaders;
2667
0
  UINT32 index = 0;
2668
2669
0
  smartcard_trace_get_status_change_return(log, ret, unicode);
2670
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
2671
0
    cReaders = 0;
2672
0
  if (cReaders == SCARD_AUTOALLOCATE)
2673
0
    cReaders = 0;
2674
2675
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
2676
0
    return SCARD_E_NO_MEMORY;
2677
2678
0
  Stream_Write_UINT32(s, cReaders); /* cReaders (4 bytes) */
2679
0
  if (!smartcard_ndr_pointer_write(s, &index, cReaders))
2680
0
    return SCARD_E_NO_MEMORY;
2681
0
  status = smartcard_ndr_write_state(s, ret->rgReaderStates, cReaders, NDR_PTR_SIMPLE);
2682
0
  if (status != SCARD_S_SUCCESS)
2683
0
    return status;
2684
0
  return ret->ReturnCode;
2685
0
}
2686
2687
LONG smartcard_unpack_state_call(wStream* s, State_Call* call)
2688
0
{
2689
0
  UINT32 index = 0;
2690
0
  UINT32 pbContextNdrPtr = 0;
2691
2692
0
  wLog* log = scard_log();
2693
2694
0
  WINPR_ASSERT(call);
2695
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2696
0
                                                     &pbContextNdrPtr);
2697
0
  if (status != SCARD_S_SUCCESS)
2698
0
    return status;
2699
2700
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2701
0
  if (status != SCARD_S_SUCCESS)
2702
0
    return status;
2703
2704
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2705
0
    return STATUS_BUFFER_TOO_SMALL;
2706
2707
0
  Stream_Read_INT32(s, call->fpbAtrIsNULL); /* fpbAtrIsNULL (4 bytes) */
2708
0
  Stream_Read_UINT32(s, call->cbAtrLen);    /* cbAtrLen (4 bytes) */
2709
2710
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2711
0
                                                    &(call->handles.hContext));
2712
0
  if (status != SCARD_S_SUCCESS)
2713
0
    return status;
2714
2715
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2716
0
  if (status != SCARD_S_SUCCESS)
2717
0
    return status;
2718
2719
0
  return status;
2720
0
}
2721
2722
LONG smartcard_pack_state_return(wStream* s, const State_Return* ret)
2723
0
{
2724
0
  WINPR_ASSERT(ret);
2725
0
  wLog* log = scard_log();
2726
0
  LONG status = 0;
2727
0
  DWORD cbAtrLen = ret->cbAtrLen;
2728
0
  UINT32 index = 0;
2729
2730
0
  smartcard_trace_state_return(log, ret);
2731
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
2732
0
    cbAtrLen = 0;
2733
0
  if (cbAtrLen == SCARD_AUTOALLOCATE)
2734
0
    cbAtrLen = 0;
2735
2736
0
  Stream_Write_UINT32(s, ret->dwState);    /* dwState (4 bytes) */
2737
0
  Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
2738
0
  Stream_Write_UINT32(s, cbAtrLen);        /* cbAtrLen (4 bytes) */
2739
0
  if (!smartcard_ndr_pointer_write(s, &index, cbAtrLen))
2740
0
    return SCARD_E_NO_MEMORY;
2741
0
  status = smartcard_ndr_write(s, ret->rgAtr, cbAtrLen, 1, NDR_PTR_SIMPLE);
2742
0
  if (status != SCARD_S_SUCCESS)
2743
0
    return status;
2744
0
  return ret->ReturnCode;
2745
0
}
2746
2747
LONG smartcard_unpack_status_call(wStream* s, Status_Call* call, BOOL unicode)
2748
0
{
2749
0
  UINT32 index = 0;
2750
0
  UINT32 pbContextNdrPtr = 0;
2751
2752
0
  WINPR_ASSERT(call);
2753
0
  wLog* log = scard_log();
2754
2755
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2756
0
                                                     &pbContextNdrPtr);
2757
0
  if (status != SCARD_S_SUCCESS)
2758
0
    return status;
2759
2760
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2761
0
  if (status != SCARD_S_SUCCESS)
2762
0
    return status;
2763
2764
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
2765
0
    return STATUS_BUFFER_TOO_SMALL;
2766
2767
0
  Stream_Read_INT32(s, call->fmszReaderNamesIsNULL); /* fmszReaderNamesIsNULL (4 bytes) */
2768
0
  Stream_Read_UINT32(s, call->cchReaderLen);         /* cchReaderLen (4 bytes) */
2769
0
  Stream_Read_UINT32(s, call->cbAtrLen);             /* cbAtrLen (4 bytes) */
2770
2771
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2772
0
                                                    &(call->handles.hContext));
2773
0
  if (status != SCARD_S_SUCCESS)
2774
0
    return status;
2775
2776
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2777
0
  if (status != SCARD_S_SUCCESS)
2778
0
    return status;
2779
2780
0
  smartcard_trace_status_call(log, call, unicode);
2781
0
  return status;
2782
0
}
2783
2784
LONG smartcard_pack_status_return(wStream* s, const Status_Return* ret, BOOL unicode)
2785
0
{
2786
0
  WINPR_ASSERT(ret);
2787
0
  wLog* log = scard_log();
2788
2789
0
  LONG status = 0;
2790
0
  UINT32 index = 0;
2791
0
  DWORD cBytes = ret->cBytes;
2792
2793
0
  smartcard_trace_status_return(log, ret, unicode);
2794
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
2795
0
    cBytes = 0;
2796
0
  if (cBytes == SCARD_AUTOALLOCATE)
2797
0
    cBytes = 0;
2798
2799
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
2800
0
    return SCARD_F_INTERNAL_ERROR;
2801
2802
0
  Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
2803
0
  if (!smartcard_ndr_pointer_write(s, &index, cBytes))
2804
0
    return SCARD_E_NO_MEMORY;
2805
2806
0
  if (!Stream_EnsureRemainingCapacity(s, 44))
2807
0
    return SCARD_F_INTERNAL_ERROR;
2808
2809
0
  Stream_Write_UINT32(s, ret->dwState);            /* dwState (4 bytes) */
2810
0
  Stream_Write_UINT32(s, ret->dwProtocol);         /* dwProtocol (4 bytes) */
2811
0
  Stream_Write(s, ret->pbAtr, sizeof(ret->pbAtr)); /* pbAtr (32 bytes) */
2812
0
  Stream_Write_UINT32(s, ret->cbAtrLen);           /* cbAtrLen (4 bytes) */
2813
0
  status = smartcard_ndr_write(s, ret->mszReaderNames, cBytes, 1, NDR_PTR_SIMPLE);
2814
0
  if (status != SCARD_S_SUCCESS)
2815
0
    return status;
2816
0
  return ret->ReturnCode;
2817
0
}
2818
2819
LONG smartcard_unpack_get_attrib_call(wStream* s, GetAttrib_Call* call)
2820
0
{
2821
0
  WINPR_ASSERT(call);
2822
0
  wLog* log = scard_log();
2823
0
  UINT32 index = 0;
2824
0
  UINT32 pbContextNdrPtr = 0;
2825
2826
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2827
0
                                                     &pbContextNdrPtr);
2828
0
  if (status != SCARD_S_SUCCESS)
2829
0
    return status;
2830
2831
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2832
0
  if (status != SCARD_S_SUCCESS)
2833
0
    return status;
2834
2835
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
2836
0
    return STATUS_BUFFER_TOO_SMALL;
2837
2838
0
  Stream_Read_UINT32(s, call->dwAttrId);     /* dwAttrId (4 bytes) */
2839
0
  Stream_Read_INT32(s, call->fpbAttrIsNULL); /* fpbAttrIsNULL (4 bytes) */
2840
0
  Stream_Read_UINT32(s, call->cbAttrLen);    /* cbAttrLen (4 bytes) */
2841
2842
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2843
0
                                                    &(call->handles.hContext));
2844
0
  if (status != SCARD_S_SUCCESS)
2845
0
    return status;
2846
2847
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2848
0
  if (status != SCARD_S_SUCCESS)
2849
0
    return status;
2850
2851
0
  smartcard_trace_get_attrib_call(log, call);
2852
0
  return status;
2853
0
}
2854
2855
LONG smartcard_pack_get_attrib_return(wStream* s, const GetAttrib_Return* ret, DWORD dwAttrId,
2856
                                      DWORD cbAttrCallLen)
2857
0
{
2858
0
  WINPR_ASSERT(ret);
2859
0
  wLog* log = scard_log();
2860
0
  LONG status = 0;
2861
0
  DWORD cbAttrLen = 0;
2862
0
  UINT32 index = 0;
2863
0
  smartcard_trace_get_attrib_return(log, ret, dwAttrId);
2864
2865
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
2866
0
    return SCARD_F_INTERNAL_ERROR;
2867
2868
0
  cbAttrLen = ret->cbAttrLen;
2869
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
2870
0
    cbAttrLen = 0;
2871
0
  if (cbAttrLen == SCARD_AUTOALLOCATE)
2872
0
    cbAttrLen = 0;
2873
2874
0
  if (ret->pbAttr)
2875
0
  {
2876
0
    if (cbAttrCallLen < cbAttrLen)
2877
0
      cbAttrLen = cbAttrCallLen;
2878
0
  }
2879
0
  Stream_Write_UINT32(s, cbAttrLen); /* cbAttrLen (4 bytes) */
2880
0
  if (!smartcard_ndr_pointer_write(s, &index, cbAttrLen))
2881
0
    return SCARD_E_NO_MEMORY;
2882
2883
0
  status = smartcard_ndr_write(s, ret->pbAttr, cbAttrLen, 1, NDR_PTR_SIMPLE);
2884
0
  if (status != SCARD_S_SUCCESS)
2885
0
    return status;
2886
0
  return ret->ReturnCode;
2887
0
}
2888
2889
LONG smartcard_unpack_control_call(wStream* s, Control_Call* call)
2890
0
{
2891
0
  WINPR_ASSERT(call);
2892
0
  wLog* log = scard_log();
2893
2894
0
  UINT32 index = 0;
2895
0
  UINT32 pvInBufferNdrPtr = 0;
2896
0
  UINT32 pbContextNdrPtr = 0;
2897
2898
0
  call->pvInBuffer = nullptr;
2899
2900
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2901
0
                                                     &pbContextNdrPtr);
2902
0
  if (status != SCARD_S_SUCCESS)
2903
0
    return status;
2904
2905
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2906
0
  if (status != SCARD_S_SUCCESS)
2907
0
    return status;
2908
2909
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 20))
2910
0
    return STATUS_BUFFER_TOO_SMALL;
2911
2912
0
  Stream_Read_UINT32(s, call->dwControlCode);                    /* dwControlCode (4 bytes) */
2913
0
  Stream_Read_UINT32(s, call->cbInBufferSize);                   /* cbInBufferSize (4 bytes) */
2914
0
  if (!smartcard_ndr_pointer_read(log, s, &index,
2915
0
                                  &pvInBufferNdrPtr)) /* pvInBufferNdrPtr (4 bytes) */
2916
0
    return ERROR_INVALID_DATA;
2917
0
  Stream_Read_INT32(s, call->fpvOutBufferIsNULL); /* fpvOutBufferIsNULL (4 bytes) */
2918
0
  Stream_Read_UINT32(s, call->cbOutBufferSize);   /* cbOutBufferSize (4 bytes) */
2919
2920
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2921
0
                                                    &(call->handles.hContext));
2922
0
  if (status != SCARD_S_SUCCESS)
2923
0
    return status;
2924
2925
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2926
0
  if (status != SCARD_S_SUCCESS)
2927
0
    return status;
2928
2929
0
  if (pvInBufferNdrPtr)
2930
0
  {
2931
0
    status =
2932
0
        smartcard_ndr_read(log, s, &call->pvInBuffer, call->cbInBufferSize, 1, NDR_PTR_SIMPLE);
2933
0
    if (status != SCARD_S_SUCCESS)
2934
0
      return status;
2935
0
  }
2936
2937
0
  smartcard_trace_control_call(log, call);
2938
0
  return SCARD_S_SUCCESS;
2939
0
}
2940
2941
LONG smartcard_pack_control_return(wStream* s, const Control_Return* ret)
2942
0
{
2943
0
  WINPR_ASSERT(ret);
2944
0
  wLog* log = scard_log();
2945
2946
0
  LONG status = 0;
2947
0
  DWORD cbDataLen = ret->cbOutBufferSize;
2948
0
  UINT32 index = 0;
2949
2950
0
  smartcard_trace_control_return(log, ret);
2951
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
2952
0
    cbDataLen = 0;
2953
0
  if (cbDataLen == SCARD_AUTOALLOCATE)
2954
0
    cbDataLen = 0;
2955
2956
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
2957
0
    return SCARD_F_INTERNAL_ERROR;
2958
2959
0
  Stream_Write_UINT32(s, cbDataLen); /* cbOutBufferSize (4 bytes) */
2960
0
  if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
2961
0
    return SCARD_E_NO_MEMORY;
2962
2963
0
  status = smartcard_ndr_write(s, ret->pvOutBuffer, cbDataLen, 1, NDR_PTR_SIMPLE);
2964
0
  if (status != SCARD_S_SUCCESS)
2965
0
    return status;
2966
0
  return ret->ReturnCode;
2967
0
}
2968
2969
LONG smartcard_unpack_transmit_call(wStream* s, Transmit_Call* call)
2970
0
{
2971
0
  UINT32 length = 0;
2972
0
  BYTE* pbExtraBytes = nullptr;
2973
0
  UINT32 pbExtraBytesNdrPtr = 0;
2974
0
  UINT32 pbSendBufferNdrPtr = 0;
2975
0
  UINT32 pioRecvPciNdrPtr = 0;
2976
0
  SCardIO_Request ioSendPci;
2977
0
  SCardIO_Request ioRecvPci;
2978
0
  UINT32 index = 0;
2979
0
  UINT32 pbContextNdrPtr = 0;
2980
2981
0
  WINPR_ASSERT(call);
2982
0
  wLog* log = scard_log();
2983
2984
0
  call->pioSendPci = nullptr;
2985
0
  call->pioRecvPci = nullptr;
2986
0
  call->pbSendBuffer = nullptr;
2987
2988
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2989
0
                                                     &pbContextNdrPtr);
2990
0
  if (status != SCARD_S_SUCCESS)
2991
0
    return status;
2992
2993
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2994
0
  if (status != SCARD_S_SUCCESS)
2995
0
    return status;
2996
2997
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 32))
2998
0
    return STATUS_BUFFER_TOO_SMALL;
2999
3000
0
  Stream_Read_UINT32(s, ioSendPci.dwProtocol);   /* dwProtocol (4 bytes) */
3001
0
  Stream_Read_UINT32(s, ioSendPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
3002
0
  if (!smartcard_ndr_pointer_read(log, s, &index,
3003
0
                                  &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
3004
0
    return ERROR_INVALID_DATA;
3005
3006
0
  Stream_Read_UINT32(s, call->cbSendLength); /* cbSendLength (4 bytes) */
3007
0
  if (!smartcard_ndr_pointer_read(log, s, &index,
3008
0
                                  &pbSendBufferNdrPtr)) /* pbSendBufferNdrPtr (4 bytes) */
3009
0
    return ERROR_INVALID_DATA;
3010
3011
0
  if (!smartcard_ndr_pointer_read(log, s, &index,
3012
0
                                  &pioRecvPciNdrPtr)) /* pioRecvPciNdrPtr (4 bytes) */
3013
0
    return ERROR_INVALID_DATA;
3014
3015
0
  Stream_Read_INT32(s, call->fpbRecvBufferIsNULL); /* fpbRecvBufferIsNULL (4 bytes) */
3016
0
  Stream_Read_UINT32(s, call->cbRecvLength);       /* cbRecvLength (4 bytes) */
3017
3018
0
  if (ioSendPci.cbExtraBytes > 1024)
3019
0
  {
3020
0
    WLog_Print(log, WLOG_WARN,
3021
0
               "Transmit_Call ioSendPci.cbExtraBytes is out of bounds: %" PRIu32 " (max: 1024)",
3022
0
               ioSendPci.cbExtraBytes);
3023
0
    return STATUS_INVALID_PARAMETER;
3024
0
  }
3025
3026
0
  if (call->cbSendLength > 66560)
3027
0
  {
3028
0
    WLog_Print(log, WLOG_WARN,
3029
0
               "Transmit_Call cbSendLength is out of bounds: %" PRIu32 " (max: 66560)",
3030
0
               ioSendPci.cbExtraBytes);
3031
0
    return STATUS_INVALID_PARAMETER;
3032
0
  }
3033
3034
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3035
0
                                                    &(call->handles.hContext));
3036
0
  if (status != SCARD_S_SUCCESS)
3037
0
    return status;
3038
3039
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3040
0
  if (status != SCARD_S_SUCCESS)
3041
0
    return status;
3042
3043
0
  if (ioSendPci.cbExtraBytes && !pbExtraBytesNdrPtr)
3044
0
  {
3045
0
    WLog_Print(
3046
0
        log, WLOG_WARN,
3047
0
        "Transmit_Call ioSendPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
3048
0
    return STATUS_INVALID_PARAMETER;
3049
0
  }
3050
3051
0
  if (pbExtraBytesNdrPtr)
3052
0
  {
3053
    // TODO: Use unified pointer reading
3054
0
    if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3055
0
      return STATUS_BUFFER_TOO_SMALL;
3056
3057
0
    Stream_Read_UINT32(s, length); /* Length (4 bytes) */
3058
3059
0
    if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ioSendPci.cbExtraBytes))
3060
0
      return STATUS_BUFFER_TOO_SMALL;
3061
3062
0
    ioSendPci.pbExtraBytes = Stream_Pointer(s);
3063
0
    call->pioSendPci =
3064
0
        (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioSendPci.cbExtraBytes);
3065
3066
0
    if (!call->pioSendPci)
3067
0
    {
3068
0
      WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioSendPci)");
3069
0
      return STATUS_NO_MEMORY;
3070
0
    }
3071
3072
0
    call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
3073
0
    call->pioSendPci->cbPciLength = (DWORD)(ioSendPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
3074
0
    pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
3075
0
    Stream_Read(s, pbExtraBytes, ioSendPci.cbExtraBytes);
3076
0
    if (smartcard_unpack_read_size_align(s, ioSendPci.cbExtraBytes, 4) < 0)
3077
0
      return STATUS_INVALID_PARAMETER;
3078
0
  }
3079
0
  else
3080
0
  {
3081
0
    call->pioSendPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
3082
3083
0
    if (!call->pioSendPci)
3084
0
    {
3085
0
      WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioSendPci)");
3086
0
      return STATUS_NO_MEMORY;
3087
0
    }
3088
3089
0
    call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
3090
0
    call->pioSendPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
3091
0
  }
3092
3093
0
  if (pbSendBufferNdrPtr)
3094
0
  {
3095
0
    status =
3096
0
        smartcard_ndr_read(log, s, &call->pbSendBuffer, call->cbSendLength, 1, NDR_PTR_SIMPLE);
3097
0
    if (status != SCARD_S_SUCCESS)
3098
0
      return status;
3099
0
  }
3100
3101
0
  if (pioRecvPciNdrPtr)
3102
0
  {
3103
0
    if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3104
0
      return STATUS_BUFFER_TOO_SMALL;
3105
3106
0
    Stream_Read_UINT32(s, ioRecvPci.dwProtocol);   /* dwProtocol (4 bytes) */
3107
0
    Stream_Read_UINT32(s, ioRecvPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
3108
0
    if (!smartcard_ndr_pointer_read(log, s, &index,
3109
0
                                    &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
3110
0
      return ERROR_INVALID_DATA;
3111
3112
0
    if (ioRecvPci.cbExtraBytes && !pbExtraBytesNdrPtr)
3113
0
    {
3114
0
      WLog_Print(
3115
0
          log, WLOG_WARN,
3116
0
          "Transmit_Call ioRecvPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
3117
0
      return STATUS_INVALID_PARAMETER;
3118
0
    }
3119
3120
0
    if (pbExtraBytesNdrPtr)
3121
0
    {
3122
      // TODO: Unify ndr pointer reading
3123
0
      if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3124
0
        return STATUS_BUFFER_TOO_SMALL;
3125
3126
0
      Stream_Read_UINT32(s, length); /* Length (4 bytes) */
3127
3128
0
      if (ioRecvPci.cbExtraBytes > 1024)
3129
0
      {
3130
0
        WLog_Print(log, WLOG_WARN,
3131
0
                   "Transmit_Call ioRecvPci.cbExtraBytes is out of bounds: %" PRIu32
3132
0
                   " (max: 1024)",
3133
0
                   ioRecvPci.cbExtraBytes);
3134
0
        return STATUS_INVALID_PARAMETER;
3135
0
      }
3136
3137
0
      if (length != ioRecvPci.cbExtraBytes)
3138
0
      {
3139
0
        WLog_Print(log, WLOG_WARN,
3140
0
                   "Transmit_Call unexpected length: Actual: %" PRIu32
3141
0
                   ", Expected: %" PRIu32 " (ioRecvPci.cbExtraBytes)",
3142
0
                   length, ioRecvPci.cbExtraBytes);
3143
0
        return STATUS_INVALID_PARAMETER;
3144
0
      }
3145
3146
0
      if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ioRecvPci.cbExtraBytes))
3147
0
        return STATUS_BUFFER_TOO_SMALL;
3148
3149
0
      ioRecvPci.pbExtraBytes = Stream_Pointer(s);
3150
0
      call->pioRecvPci =
3151
0
          (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioRecvPci.cbExtraBytes);
3152
3153
0
      if (!call->pioRecvPci)
3154
0
      {
3155
0
        WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioRecvPci)");
3156
0
        return STATUS_NO_MEMORY;
3157
0
      }
3158
3159
0
      call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
3160
0
      call->pioRecvPci->cbPciLength =
3161
0
          (DWORD)(ioRecvPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
3162
0
      pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
3163
0
      Stream_Read(s, pbExtraBytes, ioRecvPci.cbExtraBytes);
3164
0
      if (smartcard_unpack_read_size_align(s, ioRecvPci.cbExtraBytes, 4) < 0)
3165
0
        return STATUS_INVALID_PARAMETER;
3166
0
    }
3167
0
    else
3168
0
    {
3169
0
      call->pioRecvPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
3170
3171
0
      if (!call->pioRecvPci)
3172
0
      {
3173
0
        WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioRecvPci)");
3174
0
        return STATUS_NO_MEMORY;
3175
0
      }
3176
3177
0
      call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
3178
0
      call->pioRecvPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
3179
0
    }
3180
0
  }
3181
3182
0
  smartcard_trace_transmit_call(log, call);
3183
0
  return SCARD_S_SUCCESS;
3184
0
}
3185
3186
LONG smartcard_pack_transmit_return(wStream* s, const Transmit_Return* ret)
3187
0
{
3188
0
  WINPR_ASSERT(ret);
3189
0
  wLog* log = scard_log();
3190
3191
0
  LONG status = 0;
3192
0
  UINT32 index = 0;
3193
0
  LONG error = 0;
3194
0
  UINT32 cbRecvLength = ret->cbRecvLength;
3195
0
  UINT32 cbRecvPci = ret->pioRecvPci ? ret->pioRecvPci->cbPciLength : 0;
3196
3197
0
  smartcard_trace_transmit_return(log, ret);
3198
3199
0
  if (!ret->pbRecvBuffer)
3200
0
    cbRecvLength = 0;
3201
3202
0
  if (!smartcard_ndr_pointer_write(s, &index, cbRecvPci))
3203
0
    return SCARD_E_NO_MEMORY;
3204
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
3205
0
    return SCARD_E_NO_MEMORY;
3206
0
  Stream_Write_UINT32(s, cbRecvLength); /* cbRecvLength (4 bytes) */
3207
0
  if (!smartcard_ndr_pointer_write(s, &index, cbRecvLength))
3208
0
    return SCARD_E_NO_MEMORY;
3209
3210
0
  if (ret->pioRecvPci)
3211
0
  {
3212
0
    UINT32 cbExtraBytes = (UINT32)(ret->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
3213
0
    BYTE* pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
3214
3215
0
    if (!Stream_EnsureRemainingCapacity(s, cbExtraBytes + 16))
3216
0
    {
3217
0
      WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3218
0
      return SCARD_F_INTERNAL_ERROR;
3219
0
    }
3220
3221
0
    Stream_Write_UINT32(s, ret->pioRecvPci->dwProtocol); /* dwProtocol (4 bytes) */
3222
0
    Stream_Write_UINT32(s, cbExtraBytes);                /* cbExtraBytes (4 bytes) */
3223
0
    if (!smartcard_ndr_pointer_write(s, &index, cbExtraBytes))
3224
0
      return SCARD_E_NO_MEMORY;
3225
0
    error = smartcard_ndr_write(s, pbExtraBytes, cbExtraBytes, 1, NDR_PTR_SIMPLE);
3226
0
    if (error)
3227
0
      return error;
3228
0
  }
3229
3230
0
  status = smartcard_ndr_write(s, ret->pbRecvBuffer, ret->cbRecvLength, 1, NDR_PTR_SIMPLE);
3231
0
  if (status != SCARD_S_SUCCESS)
3232
0
    return status;
3233
0
  return ret->ReturnCode;
3234
0
}
3235
3236
LONG smartcard_unpack_locate_cards_by_atr_a_call(wStream* s, LocateCardsByATRA_Call* call)
3237
0
{
3238
0
  UINT32 rgReaderStatesNdrPtr = 0;
3239
0
  UINT32 rgAtrMasksNdrPtr = 0;
3240
0
  UINT32 index = 0;
3241
0
  UINT32 pbContextNdrPtr = 0;
3242
3243
0
  WINPR_ASSERT(call);
3244
0
  wLog* log = scard_log();
3245
3246
0
  call->rgReaderStates = nullptr;
3247
3248
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3249
0
                                                     &pbContextNdrPtr);
3250
0
  if (status != SCARD_S_SUCCESS)
3251
0
    return status;
3252
3253
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3254
0
    return STATUS_BUFFER_TOO_SMALL;
3255
3256
0
  Stream_Read_UINT32(s, call->cAtrs);
3257
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &rgAtrMasksNdrPtr))
3258
0
    return ERROR_INVALID_DATA;
3259
0
  Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */
3260
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &rgReaderStatesNdrPtr))
3261
0
    return ERROR_INVALID_DATA;
3262
3263
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3264
0
                                                    &(call->handles.hContext));
3265
0
  if (status != SCARD_S_SUCCESS)
3266
0
    return status;
3267
3268
0
  if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3269
0
  {
3270
0
    WLog_Print(log, WLOG_WARN,
3271
0
               "LocateCardsByATRA_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3272
0
               ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3273
0
               rgAtrMasksNdrPtr, call->cAtrs);
3274
0
    return STATUS_INVALID_PARAMETER;
3275
0
  }
3276
3277
0
  if (rgAtrMasksNdrPtr)
3278
0
  {
3279
0
    status = smartcard_ndr_read_atrmask(log, s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3280
0
    if (status != SCARD_S_SUCCESS)
3281
0
      return status;
3282
0
  }
3283
3284
0
  if (rgReaderStatesNdrPtr)
3285
0
  {
3286
0
    status =
3287
0
        smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, call->cReaders, &index);
3288
0
    if (status != SCARD_S_SUCCESS)
3289
0
      return status;
3290
0
  }
3291
3292
0
  smartcard_trace_locate_cards_by_atr_a_call(log, call);
3293
0
  return SCARD_S_SUCCESS;
3294
0
}
3295
3296
LONG smartcard_unpack_context_and_two_strings_a_call(wStream* s, ContextAndTwoStringA_Call* call)
3297
0
{
3298
0
  UINT32 sz1NdrPtr = 0;
3299
0
  UINT32 sz2NdrPtr = 0;
3300
0
  UINT32 index = 0;
3301
0
  UINT32 pbContextNdrPtr = 0;
3302
3303
0
  WINPR_ASSERT(call);
3304
0
  wLog* log = scard_log();
3305
3306
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3307
0
                                                     &pbContextNdrPtr);
3308
0
  if (status != SCARD_S_SUCCESS)
3309
0
    return status;
3310
3311
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3312
0
    return ERROR_INVALID_DATA;
3313
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3314
0
    return ERROR_INVALID_DATA;
3315
3316
0
  status =
3317
0
      smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &call->handles.hContext);
3318
0
  if (status != SCARD_S_SUCCESS)
3319
0
    return status;
3320
3321
0
  if (sz1NdrPtr)
3322
0
  {
3323
0
    status = smartcard_ndr_read_a(log, s, &call->sz1, NDR_PTR_FULL);
3324
0
    if (status != SCARD_S_SUCCESS)
3325
0
      return status;
3326
0
  }
3327
0
  if (sz2NdrPtr)
3328
0
  {
3329
0
    status = smartcard_ndr_read_a(log, s, &call->sz2, NDR_PTR_FULL);
3330
0
    if (status != SCARD_S_SUCCESS)
3331
0
      return status;
3332
0
  }
3333
0
  smartcard_trace_context_and_two_strings_a_call(log, call);
3334
0
  return SCARD_S_SUCCESS;
3335
0
}
3336
3337
LONG smartcard_unpack_context_and_two_strings_w_call(wStream* s, ContextAndTwoStringW_Call* call)
3338
0
{
3339
0
  UINT32 sz1NdrPtr = 0;
3340
0
  UINT32 sz2NdrPtr = 0;
3341
0
  UINT32 index = 0;
3342
0
  UINT32 pbContextNdrPtr = 0;
3343
3344
0
  WINPR_ASSERT(call);
3345
0
  wLog* log = scard_log();
3346
3347
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3348
0
                                                     &pbContextNdrPtr);
3349
0
  if (status != SCARD_S_SUCCESS)
3350
0
    return status;
3351
3352
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3353
0
    return ERROR_INVALID_DATA;
3354
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3355
0
    return ERROR_INVALID_DATA;
3356
3357
0
  status =
3358
0
      smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &call->handles.hContext);
3359
0
  if (status != SCARD_S_SUCCESS)
3360
0
    return status;
3361
3362
0
  if (sz1NdrPtr)
3363
0
  {
3364
0
    status = smartcard_ndr_read_w(log, s, &call->sz1, NDR_PTR_FULL);
3365
0
    if (status != SCARD_S_SUCCESS)
3366
0
      return status;
3367
0
  }
3368
0
  if (sz2NdrPtr)
3369
0
  {
3370
0
    status = smartcard_ndr_read_w(log, s, &call->sz2, NDR_PTR_FULL);
3371
0
    if (status != SCARD_S_SUCCESS)
3372
0
      return status;
3373
0
  }
3374
0
  smartcard_trace_context_and_two_strings_w_call(log, call);
3375
0
  return SCARD_S_SUCCESS;
3376
0
}
3377
3378
LONG smartcard_unpack_locate_cards_a_call(wStream* s, LocateCardsA_Call* call)
3379
0
{
3380
0
  UINT32 sz1NdrPtr = 0;
3381
0
  UINT32 sz2NdrPtr = 0;
3382
0
  UINT32 index = 0;
3383
0
  UINT32 pbContextNdrPtr = 0;
3384
3385
0
  WINPR_ASSERT(call);
3386
0
  wLog* log = scard_log();
3387
3388
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3389
0
                                                     &pbContextNdrPtr);
3390
0
  if (status != SCARD_S_SUCCESS)
3391
0
    return status;
3392
3393
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3394
0
    return STATUS_BUFFER_TOO_SMALL;
3395
3396
0
  Stream_Read_UINT32(s, call->cBytes);
3397
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3398
0
    return ERROR_INVALID_DATA;
3399
3400
0
  Stream_Read_UINT32(s, call->cReaders);
3401
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3402
0
    return ERROR_INVALID_DATA;
3403
3404
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3405
0
                                                    &(call->handles.hContext));
3406
0
  if (status != SCARD_S_SUCCESS)
3407
0
    return status;
3408
3409
0
  if (sz1NdrPtr)
3410
0
  {
3411
0
    status = smartcard_ndr_read_fixed_string_a(log, s, &call->mszCards, call->cBytes,
3412
0
                                               NDR_PTR_SIMPLE);
3413
0
    if (status != SCARD_S_SUCCESS)
3414
0
      return status;
3415
0
  }
3416
0
  if (sz2NdrPtr)
3417
0
  {
3418
0
    status =
3419
0
        smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, call->cReaders, &index);
3420
0
    if (status != SCARD_S_SUCCESS)
3421
0
      return status;
3422
0
  }
3423
0
  smartcard_trace_locate_cards_a_call(log, call);
3424
0
  return SCARD_S_SUCCESS;
3425
0
}
3426
3427
LONG smartcard_unpack_locate_cards_w_call(wStream* s, LocateCardsW_Call* call)
3428
0
{
3429
0
  UINT32 sz1NdrPtr = 0;
3430
0
  UINT32 sz2NdrPtr = 0;
3431
0
  UINT32 index = 0;
3432
0
  UINT32 pbContextNdrPtr = 0;
3433
3434
0
  WINPR_ASSERT(call);
3435
0
  wLog* log = scard_log();
3436
3437
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3438
0
                                                     &pbContextNdrPtr);
3439
0
  if (status != SCARD_S_SUCCESS)
3440
0
    return status;
3441
3442
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3443
0
    return STATUS_BUFFER_TOO_SMALL;
3444
3445
0
  Stream_Read_UINT32(s, call->cBytes);
3446
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3447
0
    return ERROR_INVALID_DATA;
3448
3449
0
  Stream_Read_UINT32(s, call->cReaders);
3450
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3451
0
    return ERROR_INVALID_DATA;
3452
3453
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3454
0
                                                    &(call->handles.hContext));
3455
0
  if (status != SCARD_S_SUCCESS)
3456
0
    return status;
3457
3458
0
  if (sz1NdrPtr)
3459
0
  {
3460
0
    status = smartcard_ndr_read_fixed_string_w(log, s, &call->mszCards, call->cBytes,
3461
0
                                               NDR_PTR_SIMPLE);
3462
0
    if (status != SCARD_S_SUCCESS)
3463
0
      return status;
3464
0
  }
3465
0
  if (sz2NdrPtr)
3466
0
  {
3467
0
    status =
3468
0
        smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, call->cReaders, &index);
3469
0
    if (status != SCARD_S_SUCCESS)
3470
0
      return status;
3471
0
  }
3472
0
  smartcard_trace_locate_cards_w_call(log, call);
3473
0
  return SCARD_S_SUCCESS;
3474
0
}
3475
3476
LONG smartcard_unpack_set_attrib_call(wStream* s, SetAttrib_Call* call)
3477
0
{
3478
0
  UINT32 index = 0;
3479
0
  UINT32 ndrPtr = 0;
3480
0
  UINT32 pbContextNdrPtr = 0;
3481
3482
0
  WINPR_ASSERT(call);
3483
0
  wLog* log = scard_log();
3484
3485
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3486
0
                                                     &pbContextNdrPtr);
3487
0
  if (status != SCARD_S_SUCCESS)
3488
0
    return status;
3489
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3490
0
  if (status != SCARD_S_SUCCESS)
3491
0
    return status;
3492
3493
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3494
0
    return STATUS_BUFFER_TOO_SMALL;
3495
0
  Stream_Read_UINT32(s, call->dwAttrId);
3496
0
  Stream_Read_UINT32(s, call->cbAttrLen);
3497
3498
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
3499
0
    return ERROR_INVALID_DATA;
3500
3501
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3502
0
                                                    &(call->handles.hContext));
3503
0
  if (status != SCARD_S_SUCCESS)
3504
0
    return status;
3505
3506
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3507
0
  if (status != SCARD_S_SUCCESS)
3508
0
    return status;
3509
3510
0
  if (ndrPtr)
3511
0
  {
3512
0
    size_t len = 0;
3513
0
    status = smartcard_ndr_read_ex(log, s, &call->pbAttr, 0, 1, NDR_PTR_SIMPLE, &len);
3514
0
    if (status != SCARD_S_SUCCESS)
3515
0
      return status;
3516
0
    if (call->cbAttrLen > len)
3517
0
      call->cbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, len);
3518
0
  }
3519
0
  else
3520
0
    call->cbAttrLen = 0;
3521
0
  smartcard_trace_set_attrib_call(log, call);
3522
0
  return SCARD_S_SUCCESS;
3523
0
}
3524
3525
LONG smartcard_unpack_locate_cards_by_atr_w_call(wStream* s, LocateCardsByATRW_Call* call)
3526
0
{
3527
0
  UINT32 rgReaderStatesNdrPtr = 0;
3528
0
  UINT32 rgAtrMasksNdrPtr = 0;
3529
0
  UINT32 index = 0;
3530
0
  UINT32 pbContextNdrPtr = 0;
3531
3532
0
  WINPR_ASSERT(call);
3533
0
  wLog* log = scard_log();
3534
3535
0
  call->rgReaderStates = nullptr;
3536
3537
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3538
0
                                                     &pbContextNdrPtr);
3539
0
  if (status != SCARD_S_SUCCESS)
3540
0
    return status;
3541
3542
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3543
0
    return STATUS_BUFFER_TOO_SMALL;
3544
3545
0
  Stream_Read_UINT32(s, call->cAtrs);
3546
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &rgAtrMasksNdrPtr))
3547
0
    return ERROR_INVALID_DATA;
3548
3549
0
  Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */
3550
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &rgReaderStatesNdrPtr))
3551
0
    return ERROR_INVALID_DATA;
3552
3553
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3554
0
                                                    &(call->handles.hContext));
3555
0
  if (status != SCARD_S_SUCCESS)
3556
0
    return status;
3557
3558
0
  if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3559
0
  {
3560
0
    WLog_Print(log, WLOG_WARN,
3561
0
               "LocateCardsByATRW_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3562
0
               ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3563
0
               rgAtrMasksNdrPtr, call->cAtrs);
3564
0
    return STATUS_INVALID_PARAMETER;
3565
0
  }
3566
3567
0
  if (rgAtrMasksNdrPtr)
3568
0
  {
3569
0
    status = smartcard_ndr_read_atrmask(log, s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3570
0
    if (status != SCARD_S_SUCCESS)
3571
0
      return status;
3572
0
  }
3573
3574
0
  if (rgReaderStatesNdrPtr)
3575
0
  {
3576
0
    status =
3577
0
        smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, call->cReaders, &index);
3578
0
    if (status != SCARD_S_SUCCESS)
3579
0
      return status;
3580
0
  }
3581
3582
0
  smartcard_trace_locate_cards_by_atr_w_call(log, call);
3583
0
  return SCARD_S_SUCCESS;
3584
0
}
3585
3586
LONG smartcard_unpack_read_cache_a_call(wStream* s, ReadCacheA_Call* call)
3587
0
{
3588
0
  UINT32 mszNdrPtr = 0;
3589
0
  UINT32 contextNdrPtr = 0;
3590
0
  UINT32 index = 0;
3591
0
  UINT32 pbContextNdrPtr = 0;
3592
3593
0
  WINPR_ASSERT(call);
3594
0
  wLog* log = scard_log();
3595
3596
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3597
0
    return ERROR_INVALID_DATA;
3598
3599
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3600
0
                                                     &index, &pbContextNdrPtr);
3601
0
  if (status != SCARD_S_SUCCESS)
3602
0
    return status;
3603
3604
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3605
0
    return ERROR_INVALID_DATA;
3606
3607
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3608
0
    return STATUS_BUFFER_TOO_SMALL;
3609
0
  Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3610
0
  Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
3611
0
  Stream_Read_UINT32(s, call->Common.cbDataLen);
3612
3613
0
  call->szLookupName = nullptr;
3614
0
  if (mszNdrPtr)
3615
0
  {
3616
0
    status = smartcard_ndr_read_a(log, s, &call->szLookupName, NDR_PTR_FULL);
3617
0
    if (status != SCARD_S_SUCCESS)
3618
0
      return status;
3619
0
  }
3620
3621
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3622
0
                                                    &call->Common.handles.hContext);
3623
0
  if (status != SCARD_S_SUCCESS)
3624
0
    return status;
3625
3626
0
  if (contextNdrPtr)
3627
0
  {
3628
0
    status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3629
0
    if (status != SCARD_S_SUCCESS)
3630
0
      return status;
3631
0
  }
3632
0
  smartcard_trace_read_cache_a_call(log, call);
3633
0
  return SCARD_S_SUCCESS;
3634
0
}
3635
3636
LONG smartcard_unpack_read_cache_w_call(wStream* s, ReadCacheW_Call* call)
3637
0
{
3638
0
  UINT32 mszNdrPtr = 0;
3639
0
  UINT32 contextNdrPtr = 0;
3640
0
  UINT32 index = 0;
3641
0
  UINT32 pbContextNdrPtr = 0;
3642
3643
0
  WINPR_ASSERT(call);
3644
0
  wLog* log = scard_log();
3645
3646
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3647
0
    return ERROR_INVALID_DATA;
3648
3649
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3650
0
                                                     &index, &pbContextNdrPtr);
3651
0
  if (status != SCARD_S_SUCCESS)
3652
0
    return status;
3653
3654
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3655
0
    return ERROR_INVALID_DATA;
3656
3657
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3658
0
    return STATUS_BUFFER_TOO_SMALL;
3659
0
  Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3660
0
  Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
3661
0
  Stream_Read_UINT32(s, call->Common.cbDataLen);
3662
3663
0
  call->szLookupName = nullptr;
3664
0
  if (mszNdrPtr)
3665
0
  {
3666
0
    status = smartcard_ndr_read_w(log, s, &call->szLookupName, NDR_PTR_FULL);
3667
0
    if (status != SCARD_S_SUCCESS)
3668
0
      return status;
3669
0
  }
3670
3671
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3672
0
                                                    &call->Common.handles.hContext);
3673
0
  if (status != SCARD_S_SUCCESS)
3674
0
    return status;
3675
3676
0
  if (contextNdrPtr)
3677
0
  {
3678
0
    status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3679
0
    if (status != SCARD_S_SUCCESS)
3680
0
      return status;
3681
0
  }
3682
0
  smartcard_trace_read_cache_w_call(log, call);
3683
0
  return SCARD_S_SUCCESS;
3684
0
}
3685
3686
LONG smartcard_unpack_write_cache_a_call(wStream* s, WriteCacheA_Call* call)
3687
0
{
3688
0
  UINT32 mszNdrPtr = 0;
3689
0
  UINT32 contextNdrPtr = 0;
3690
0
  UINT32 pbDataNdrPtr = 0;
3691
0
  UINT32 index = 0;
3692
0
  UINT32 pbContextNdrPtr = 0;
3693
3694
0
  WINPR_ASSERT(call);
3695
0
  wLog* log = scard_log();
3696
3697
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3698
0
    return ERROR_INVALID_DATA;
3699
3700
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3701
0
                                                     &index, &pbContextNdrPtr);
3702
0
  if (status != SCARD_S_SUCCESS)
3703
0
    return status;
3704
3705
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3706
0
    return ERROR_INVALID_DATA;
3707
3708
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
3709
0
    return STATUS_BUFFER_TOO_SMALL;
3710
3711
0
  Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3712
0
  Stream_Read_UINT32(s, call->Common.cbDataLen);
3713
3714
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &pbDataNdrPtr))
3715
0
    return ERROR_INVALID_DATA;
3716
3717
0
  call->szLookupName = nullptr;
3718
0
  if (mszNdrPtr)
3719
0
  {
3720
0
    status = smartcard_ndr_read_a(log, s, &call->szLookupName, NDR_PTR_FULL);
3721
0
    if (status != SCARD_S_SUCCESS)
3722
0
      return status;
3723
0
  }
3724
3725
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3726
0
                                                    &call->Common.handles.hContext);
3727
0
  if (status != SCARD_S_SUCCESS)
3728
0
    return status;
3729
3730
0
  call->Common.CardIdentifier = nullptr;
3731
0
  if (contextNdrPtr)
3732
0
  {
3733
0
    status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3734
0
    if (status != SCARD_S_SUCCESS)
3735
0
      return status;
3736
0
  }
3737
3738
0
  call->Common.pbData = nullptr;
3739
0
  if (pbDataNdrPtr)
3740
0
  {
3741
0
    status = smartcard_ndr_read(log, s, &call->Common.pbData, call->Common.cbDataLen, 1,
3742
0
                                NDR_PTR_SIMPLE);
3743
0
    if (status != SCARD_S_SUCCESS)
3744
0
      return status;
3745
0
  }
3746
0
  smartcard_trace_write_cache_a_call(log, call);
3747
0
  return SCARD_S_SUCCESS;
3748
0
}
3749
3750
LONG smartcard_unpack_write_cache_w_call(wStream* s, WriteCacheW_Call* call)
3751
0
{
3752
0
  UINT32 mszNdrPtr = 0;
3753
0
  UINT32 contextNdrPtr = 0;
3754
0
  UINT32 pbDataNdrPtr = 0;
3755
0
  UINT32 index = 0;
3756
0
  UINT32 pbContextNdrPtr = 0;
3757
3758
0
  WINPR_ASSERT(call);
3759
0
  wLog* log = scard_log();
3760
3761
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3762
0
    return ERROR_INVALID_DATA;
3763
3764
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3765
0
                                                     &index, &pbContextNdrPtr);
3766
0
  if (status != SCARD_S_SUCCESS)
3767
0
    return status;
3768
3769
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3770
0
    return ERROR_INVALID_DATA;
3771
3772
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
3773
0
    return STATUS_BUFFER_TOO_SMALL;
3774
0
  Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3775
0
  Stream_Read_UINT32(s, call->Common.cbDataLen);
3776
3777
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &pbDataNdrPtr))
3778
0
    return ERROR_INVALID_DATA;
3779
3780
0
  call->szLookupName = nullptr;
3781
0
  if (mszNdrPtr)
3782
0
  {
3783
0
    status = smartcard_ndr_read_w(log, s, &call->szLookupName, NDR_PTR_FULL);
3784
0
    if (status != SCARD_S_SUCCESS)
3785
0
      return status;
3786
0
  }
3787
3788
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3789
0
                                                    &call->Common.handles.hContext);
3790
0
  if (status != SCARD_S_SUCCESS)
3791
0
    return status;
3792
3793
0
  call->Common.CardIdentifier = nullptr;
3794
0
  if (contextNdrPtr)
3795
0
  {
3796
0
    status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3797
0
    if (status != SCARD_S_SUCCESS)
3798
0
      return status;
3799
0
  }
3800
3801
0
  call->Common.pbData = nullptr;
3802
0
  if (pbDataNdrPtr)
3803
0
  {
3804
0
    status = smartcard_ndr_read(log, s, &call->Common.pbData, call->Common.cbDataLen, 1,
3805
0
                                NDR_PTR_SIMPLE);
3806
0
    if (status != SCARD_S_SUCCESS)
3807
0
      return status;
3808
0
  }
3809
0
  smartcard_trace_write_cache_w_call(log, call);
3810
0
  return status;
3811
0
}
3812
3813
LONG smartcard_unpack_get_transmit_count_call(wStream* s, GetTransmitCount_Call* call)
3814
0
{
3815
0
  WINPR_ASSERT(call);
3816
0
  wLog* log = scard_log();
3817
3818
0
  UINT32 index = 0;
3819
0
  UINT32 pbContextNdrPtr = 0;
3820
3821
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3822
0
                                                     &pbContextNdrPtr);
3823
0
  if (status != SCARD_S_SUCCESS)
3824
0
    return status;
3825
3826
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3827
0
  if (status != SCARD_S_SUCCESS)
3828
0
    return status;
3829
3830
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3831
0
                                                    &(call->handles.hContext));
3832
0
  if (status != SCARD_S_SUCCESS)
3833
0
  {
3834
0
    WLog_Print(log, WLOG_ERROR,
3835
0
               "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
3836
0
               status);
3837
0
    return status;
3838
0
  }
3839
3840
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3841
0
  if (status != SCARD_S_SUCCESS)
3842
0
    WLog_Print(log, WLOG_ERROR,
3843
0
               "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status);
3844
3845
0
  smartcard_trace_get_transmit_count_call(log, call);
3846
0
  return status;
3847
0
}
3848
3849
LONG smartcard_unpack_get_reader_icon_call(wStream* s, GetReaderIcon_Call* call)
3850
0
{
3851
0
  WINPR_ASSERT(call);
3852
0
  wLog* log = scard_log();
3853
0
  return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext,
3854
0
                                                      &call->szReaderName);
3855
0
}
3856
3857
LONG smartcard_unpack_context_and_string_a_call(wStream* s, ContextAndStringA_Call* call)
3858
0
{
3859
0
  WINPR_ASSERT(call);
3860
0
  wLog* log = scard_log();
3861
0
  return smartcard_unpack_common_context_and_string_a(log, s, &call->handles.hContext, &call->sz);
3862
0
}
3863
3864
LONG smartcard_unpack_context_and_string_w_call(wStream* s, ContextAndStringW_Call* call)
3865
0
{
3866
0
  WINPR_ASSERT(call);
3867
0
  wLog* log = scard_log();
3868
0
  return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext, &call->sz);
3869
0
}
3870
3871
LONG smartcard_unpack_get_device_type_id_call(wStream* s, GetDeviceTypeId_Call* call)
3872
0
{
3873
0
  WINPR_ASSERT(call);
3874
0
  wLog* log = scard_log();
3875
0
  return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext,
3876
0
                                                      &call->szReaderName);
3877
0
}
3878
3879
LONG smartcard_pack_device_type_id_return(wStream* s, const GetDeviceTypeId_Return* ret)
3880
0
{
3881
0
  WINPR_ASSERT(ret);
3882
0
  wLog* log = scard_log();
3883
0
  smartcard_trace_device_type_id_return(log, ret);
3884
3885
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
3886
0
  {
3887
0
    WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3888
0
    return SCARD_F_INTERNAL_ERROR;
3889
0
  }
3890
3891
0
  Stream_Write_UINT32(s, ret->dwDeviceId); /* cBytes (4 bytes) */
3892
3893
0
  return ret->ReturnCode;
3894
0
}
3895
3896
LONG smartcard_pack_locate_cards_return(wStream* s, const LocateCards_Return* ret)
3897
0
{
3898
0
  WINPR_ASSERT(ret);
3899
0
  wLog* log = scard_log();
3900
3901
0
  LONG status = 0;
3902
0
  DWORD cbDataLen = ret->cReaders;
3903
0
  UINT32 index = 0;
3904
3905
0
  smartcard_trace_locate_cards_return(log, ret);
3906
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
3907
0
    cbDataLen = 0;
3908
0
  if (cbDataLen == SCARD_AUTOALLOCATE)
3909
0
    cbDataLen = 0;
3910
3911
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
3912
0
  {
3913
0
    WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3914
0
    return SCARD_F_INTERNAL_ERROR;
3915
0
  }
3916
3917
0
  Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
3918
0
  if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3919
0
    return SCARD_E_NO_MEMORY;
3920
3921
0
  status = smartcard_ndr_write_state(s, ret->rgReaderStates, cbDataLen, NDR_PTR_SIMPLE);
3922
0
  if (status != SCARD_S_SUCCESS)
3923
0
    return status;
3924
0
  return ret->ReturnCode;
3925
0
}
3926
3927
LONG smartcard_pack_get_reader_icon_return(wStream* s, const GetReaderIcon_Return* ret)
3928
0
{
3929
0
  WINPR_ASSERT(ret);
3930
0
  wLog* log = scard_log();
3931
3932
0
  LONG status = 0;
3933
0
  UINT32 index = 0;
3934
0
  DWORD cbDataLen = ret->cbDataLen;
3935
0
  smartcard_trace_get_reader_icon_return(log, ret);
3936
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
3937
0
    cbDataLen = 0;
3938
0
  if (cbDataLen == SCARD_AUTOALLOCATE)
3939
0
    cbDataLen = 0;
3940
3941
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
3942
0
  {
3943
0
    WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3944
0
    return SCARD_F_INTERNAL_ERROR;
3945
0
  }
3946
3947
0
  Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
3948
0
  if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3949
0
    return SCARD_E_NO_MEMORY;
3950
3951
0
  status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
3952
0
  if (status != SCARD_S_SUCCESS)
3953
0
    return status;
3954
0
  return ret->ReturnCode;
3955
0
}
3956
3957
LONG smartcard_pack_get_transmit_count_return(wStream* s, const GetTransmitCount_Return* call)
3958
0
{
3959
0
  WINPR_ASSERT(call);
3960
0
  wLog* log = scard_log();
3961
3962
0
  smartcard_trace_get_transmit_count_return(log, call);
3963
3964
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
3965
0
  {
3966
0
    WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3967
0
    return SCARD_F_INTERNAL_ERROR;
3968
0
  }
3969
3970
0
  Stream_Write_UINT32(s, call->cTransmitCount); /* cBytes (4 cbDataLen) */
3971
3972
0
  return call->ReturnCode;
3973
0
}
3974
3975
LONG smartcard_pack_read_cache_return(wStream* s, const ReadCache_Return* ret)
3976
0
{
3977
0
  WINPR_ASSERT(ret);
3978
0
  wLog* log = scard_log();
3979
3980
0
  LONG status = 0;
3981
0
  UINT32 index = 0;
3982
0
  DWORD cbDataLen = ret->cbDataLen;
3983
0
  smartcard_trace_read_cache_return(log, ret);
3984
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
3985
0
    cbDataLen = 0;
3986
3987
0
  if (cbDataLen == SCARD_AUTOALLOCATE)
3988
0
    cbDataLen = 0;
3989
3990
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
3991
0
  {
3992
0
    WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3993
0
    return SCARD_F_INTERNAL_ERROR;
3994
0
  }
3995
3996
0
  Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
3997
0
  if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3998
0
    return SCARD_E_NO_MEMORY;
3999
4000
0
  status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4001
0
  if (status != SCARD_S_SUCCESS)
4002
0
    return status;
4003
0
  return ret->ReturnCode;
4004
0
}