Coverage Report

Created: 2026-09-01 06:39

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, UINT32* 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, UINT32* 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, const 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
  *data = r;
209
0
  if (plen)
210
0
    *plen = len; /* payload bytes only, excluding the NDR alignment padding */
211
0
  return STATUS_SUCCESS;
212
0
}
213
214
static LONG smartcard_ndr_read(wLog* log, wStream* s, BYTE** data, size_t min, size_t elementSize,
215
                               const ndr_ptr_t type)
216
0
{
217
0
  return smartcard_ndr_read_ex(log, s, data, min, elementSize, type, nullptr);
218
0
}
219
220
static BOOL smartcard_ndr_pointer_write(wStream* s, UINT32* index, UINT32 length)
221
0
{
222
0
  const UINT32 ndrPtr = 0x20000 + (*index) * 4;
223
224
0
  if (!s)
225
0
    return FALSE;
226
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
227
0
    return FALSE;
228
229
0
  if (length > 0)
230
0
  {
231
0
    Stream_Write_UINT32(s, ndrPtr); /* mszGroupsNdrPtr (4 bytes) */
232
0
    (*index) = (*index) + 1;
233
0
  }
234
0
  else
235
0
    Stream_Write_UINT32(s, 0);
236
0
  return TRUE;
237
0
}
238
239
static LONG smartcard_ndr_write(wStream* s, const BYTE* data, UINT32 size, UINT32 elementSize,
240
                                const ndr_ptr_t type)
241
0
{
242
0
  const UINT32 offset = 0;
243
0
  const UINT32 len = size;
244
0
  const UINT32 dataLen = size * elementSize;
245
0
  size_t required = 0;
246
247
0
  if (size == 0)
248
0
    return SCARD_S_SUCCESS;
249
250
0
  switch (type)
251
0
  {
252
0
    case NDR_PTR_FULL:
253
0
      required = 12;
254
0
      break;
255
0
    case NDR_PTR_SIMPLE:
256
0
      required = 4;
257
0
      break;
258
0
    case NDR_PTR_FIXED:
259
0
      required = 0;
260
0
      break;
261
0
    default:
262
0
      return SCARD_E_INVALID_PARAMETER;
263
0
  }
264
265
0
  if (!Stream_EnsureRemainingCapacity(s, required + dataLen + 4))
266
0
    return STATUS_BUFFER_TOO_SMALL;
267
268
0
  switch (type)
269
0
  {
270
0
    case NDR_PTR_FULL:
271
0
      Stream_Write_UINT32(s, len);
272
0
      Stream_Write_UINT32(s, offset);
273
0
      Stream_Write_UINT32(s, len);
274
0
      break;
275
0
    case NDR_PTR_SIMPLE:
276
0
      Stream_Write_UINT32(s, len);
277
0
      break;
278
0
    case NDR_PTR_FIXED:
279
0
      break;
280
0
    default:
281
0
      return SCARD_E_INVALID_PARAMETER;
282
0
  }
283
284
0
  if (data)
285
0
    Stream_Write(s, data, dataLen);
286
0
  else
287
0
    Stream_Zero(s, dataLen);
288
0
  return smartcard_pack_write_size_align(s, dataLen, 4);
289
0
}
290
291
static LONG smartcard_ndr_write_state(wStream* s, const ReaderState_Return* data, UINT32 size,
292
                                      const ndr_ptr_t type)
293
0
{
294
0
  union
295
0
  {
296
0
    const ReaderState_Return* reader;
297
0
    const BYTE* data;
298
0
  } cnv;
299
300
0
  WINPR_ASSERT(data || (size == 0));
301
0
  cnv.reader = data;
302
303
0
  for (size_t x = 0; x < size; x++)
304
0
  {
305
0
    const ReaderState_Return* cur = &data[x];
306
0
    if (!smartcard_reader_state_return_is_valid(x, cur))
307
0
      return SCARD_E_INVALID_ATR;
308
0
  }
309
0
  return smartcard_ndr_write(s, cnv.data, size, sizeof(ReaderState_Return), type);
310
0
}
311
312
static LONG smartcard_ndr_read_state(wLog* log, wStream* s, ReaderState_Return** data, size_t min,
313
                                     const ndr_ptr_t type)
314
0
{
315
0
  union
316
0
  {
317
0
    ReaderState_Return** ppc;
318
0
    BYTE** ppv;
319
0
  } u;
320
321
0
  WINPR_ASSERT(data);
322
0
  u.ppc = data;
323
324
0
  size_t len = 0;
325
0
  const LONG status =
326
0
      smartcard_ndr_read_ex(log, s, u.ppv, min, sizeof(ReaderState_Return), type, &len);
327
0
  if (status != SCARD_S_SUCCESS)
328
0
    return status;
329
330
0
  if (len / sizeof(ReaderState_Return) < min)
331
0
    return SCARD_E_INVALID_VALUE;
332
333
0
  for (size_t x = 0; x < min; x++)
334
0
  {
335
0
    const ReaderState_Return* cur = &(*data)[x];
336
0
    if (!smartcard_reader_state_return_is_valid(x, cur))
337
0
      return SCARD_E_INVALID_ATR;
338
0
  }
339
0
  return status;
340
0
}
341
342
static LONG smartcard_ndr_read_atrmask(wLog* log, wStream* s, LocateCards_ATRMask** data,
343
                                       size_t min, const ndr_ptr_t type)
344
0
{
345
0
  union
346
0
  {
347
0
    LocateCards_ATRMask** ppc;
348
0
    BYTE** ppv;
349
0
  } u;
350
0
  u.ppc = data;
351
0
  const LONG status = smartcard_ndr_read(log, s, u.ppv, min, sizeof(LocateCards_ATRMask), type);
352
0
  if (status != SCARD_S_SUCCESS)
353
0
    return status;
354
355
  /* [MS-RDPESC] 2.2.1.5: cbAtr is range(0..36), the number of valid bytes in the fixed
356
   * rgbAtr/rgbMask arrays. A larger value walks past them when the mask is compared byte
357
   * by byte, so reject it here rather than trusting the wire value. */
358
0
  LocateCards_ATRMask* masks = *data;
359
0
  for (size_t x = 0; x < min; x++)
360
0
  {
361
0
    const UINT32 val = winpr_Data_Get_UINT32(&masks[x].cbAtr);
362
0
    if (val > ARRAYSIZE(masks[x].rgbAtr))
363
0
    {
364
0
      WLog_Print(log, WLOG_ERROR,
365
0
                 "LocateCards_ATRMask[%" PRIuz "]::cbAtr %" PRIu32 " exceeds %" PRIuz, x, val,
366
0
                 (size_t)ARRAYSIZE(masks[x].rgbAtr));
367
0
      free(*data);
368
0
      *data = nullptr;
369
0
      return STATUS_DATA_ERROR;
370
0
    }
371
0
  }
372
0
  return SCARD_S_SUCCESS;
373
0
}
374
375
static LONG smartcard_ndr_read_fixed_string_a(wLog* log, wStream* s, CHAR** data, size_t min,
376
                                              const ndr_ptr_t type)
377
0
{
378
0
  union
379
0
  {
380
0
    CHAR** ppc;
381
0
    BYTE** ppv;
382
0
  } u;
383
0
  u.ppc = data;
384
0
  return smartcard_ndr_read(log, s, u.ppv, min, sizeof(CHAR), type);
385
0
}
386
387
static LONG smartcard_ndr_read_fixed_string_w(wLog* log, wStream* s, WCHAR** data, size_t min,
388
                                              const ndr_ptr_t type)
389
0
{
390
0
  union
391
0
  {
392
0
    WCHAR** ppc;
393
0
    BYTE** ppv;
394
0
  } u;
395
0
  u.ppc = data;
396
0
  return smartcard_ndr_read(log, s, u.ppv, min, sizeof(WCHAR), type);
397
0
}
398
399
static LONG smartcard_ndr_read_a(wLog* log, wStream* s, CHAR** data, const ndr_ptr_t type)
400
0
{
401
0
  union
402
0
  {
403
0
    CHAR** ppc;
404
0
    BYTE** ppv;
405
0
  } u;
406
0
  u.ppc = data;
407
0
  return smartcard_ndr_read(log, s, u.ppv, 0, sizeof(CHAR), type);
408
0
}
409
410
static LONG smartcard_ndr_read_w(wLog* log, wStream* s, WCHAR** data, const ndr_ptr_t type)
411
0
{
412
0
  union
413
0
  {
414
0
    WCHAR** ppc;
415
0
    BYTE** ppv;
416
0
  } u;
417
0
  u.ppc = data;
418
0
  return smartcard_ndr_read(log, s, u.ppv, 0, sizeof(WCHAR), type);
419
0
}
420
421
static LONG smartcard_ndr_write_w(wStream* s, const WCHAR* data, UINT32 size, const ndr_ptr_t type)
422
0
{
423
0
  union
424
0
  {
425
0
    const WCHAR* wz;
426
0
    const BYTE* bp;
427
0
  } cnv;
428
0
  cnv.wz = data;
429
0
  return smartcard_ndr_write(s, cnv.bp, size, sizeof(WCHAR), type);
430
0
}
431
432
static LONG smartcard_ndr_write_a(wStream* s, const CHAR* data, UINT32 size, const ndr_ptr_t type)
433
0
{
434
0
  union
435
0
  {
436
0
    const CHAR* sz;
437
0
    const BYTE* bp;
438
0
  } cnv;
439
0
  cnv.sz = data;
440
0
  return smartcard_ndr_write(s, cnv.bp, size, sizeof(CHAR), type);
441
0
}
442
443
static LONG smartcard_ndr_read_u(wLog* log, wStream* s, UUID** data)
444
0
{
445
0
  union
446
0
  {
447
0
    UUID** ppc;
448
0
    BYTE** ppv;
449
0
  } u;
450
0
  u.ppc = data;
451
0
  return smartcard_ndr_read(log, s, u.ppv, 1, sizeof(UUID), NDR_PTR_FIXED);
452
0
}
453
454
static char* smartcard_convert_string_list(const void* in, size_t bytes, BOOL unicode)
455
0
{
456
0
  size_t length = 0;
457
0
  union
458
0
  {
459
0
    const void* pv;
460
0
    const char* sz;
461
0
    const WCHAR* wz;
462
0
  } string;
463
0
  char* mszA = nullptr;
464
465
0
  string.pv = in;
466
467
0
  if (bytes < 1)
468
0
    return nullptr;
469
470
0
  if (in == nullptr)
471
0
    return nullptr;
472
473
0
  if (unicode)
474
0
  {
475
0
    mszA = ConvertMszWCharNToUtf8Alloc(string.wz, bytes / sizeof(WCHAR), &length);
476
0
    if (!mszA)
477
0
      return nullptr;
478
0
  }
479
0
  else
480
0
  {
481
0
    mszA = (char*)calloc(bytes, sizeof(char));
482
0
    if (!mszA)
483
0
      return nullptr;
484
0
    CopyMemory(mszA, string.sz, bytes - 1);
485
0
    length = bytes;
486
0
  }
487
488
0
  if (length < 1)
489
0
  {
490
0
    free(mszA);
491
0
    return nullptr;
492
0
  }
493
0
  for (size_t index = 0; index < length - 1; index++)
494
0
  {
495
0
    if (mszA[index] == '\0')
496
0
      mszA[index] = ',';
497
0
  }
498
499
0
  return mszA;
500
0
}
501
502
WINPR_ATTR_MALLOC(free, 1)
503
static char* smartcard_create_msz_dump(const char* msz, size_t len)
504
0
{
505
0
  size_t bufferLen = len;
506
0
  char* buffer = calloc(len + 1, 1);
507
0
  if (!buffer)
508
0
    return nullptr;
509
510
0
  char* buf = buffer;
511
0
  const char* cur = msz;
512
513
0
  while ((len > 0) && cur && cur[0] != '\0' && (bufferLen > 0))
514
0
  {
515
0
    size_t clen = strnlen(cur, len);
516
0
    int rc = _snprintf(buf, bufferLen, "%s", cur);
517
0
    bufferLen -= (size_t)rc;
518
0
    buf += rc;
519
520
0
    cur += clen;
521
0
  }
522
523
0
  return buffer;
524
0
}
525
526
static void smartcard_msz_dump(wLog* log, DWORD level, const char* prefix, const void* data,
527
                               size_t len, UINT32 wchar)
528
0
{
529
0
  if (!WLog_IsLevelActive(log, level))
530
0
    return;
531
532
0
  char* tmp = nullptr;
533
0
  const char* msz = WINPR_CXX_COMPAT_CAST(const char*, data);
534
0
  size_t mszlen = len;
535
0
  if (wchar)
536
0
  {
537
0
    tmp = ConvertMszWCharNToUtf8Alloc(data, len, &mszlen);
538
0
    msz = tmp;
539
0
  }
540
541
0
  char* array = smartcard_create_msz_dump(msz, mszlen);
542
0
  WLog_Print(log, level, "%s%s", prefix, array);
543
0
  free(array);
544
0
  free(tmp);
545
0
}
546
547
WINPR_ATTR_MALLOC(free, 1)
548
static char* smartcard_create_array_dump(const void* pd, size_t len)
549
0
{
550
0
  const BYTE* data = pd;
551
0
  int rc = 0;
552
553
0
  size_t bufferLen = len * 4;
554
0
  if (bufferLen < 32)
555
0
    bufferLen = 32;
556
0
  char* buffer = calloc(bufferLen + 1, 1);
557
0
  if (!buffer)
558
0
    return nullptr;
559
0
  char* start = buffer;
560
561
0
  WINPR_ASSERT(buffer || (bufferLen == 0));
562
563
0
  if (!data && (len > 0))
564
0
  {
565
0
    (void)_snprintf(buffer, bufferLen, "{ nullptr [%" PRIuz "] }", len);
566
0
    goto fail;
567
0
  }
568
569
0
  rc = _snprintf(buffer, bufferLen, "{ ");
570
0
  if ((rc < 0) || ((size_t)rc >= bufferLen))
571
0
    goto fail;
572
0
  buffer += rc;
573
0
  bufferLen -= (size_t)rc;
574
575
0
  for (size_t x = 0; x < len; x++)
576
0
  {
577
0
    rc = _snprintf(buffer, bufferLen, "%02X", data[x]);
578
0
    if ((rc < 0) || ((size_t)rc >= bufferLen))
579
0
      goto fail;
580
0
    buffer += rc;
581
0
    bufferLen -= (size_t)rc;
582
0
  }
583
584
0
  rc = _snprintf(buffer, bufferLen, " }");
585
0
  if ((rc < 0) || ((size_t)rc >= bufferLen))
586
0
    goto fail;
587
588
0
fail:
589
0
  return start;
590
0
}
591
592
WINPR_ATTR_FORMAT_ARG(3, 7)
593
static void smartcard_dump_array(wLog* log, DWORD level, WINPR_FORMAT_ARG const char* prefix,
594
                                 const char* postfix, const void* data, size_t len, ...)
595
0
{
596
0
  if (!WLog_IsLevelActive(log, level))
597
0
    return;
598
599
0
  char* buffer = smartcard_create_array_dump(data, len);
600
601
0
  char* fprefix = nullptr;
602
0
  size_t flen = 0;
603
0
  va_list ap = WINPR_C_ARRAY_INIT;
604
0
  va_start(ap, len);
605
0
  winpr_vasprintf(&fprefix, &flen, prefix, ap);
606
0
  va_end(ap);
607
0
  WLog_Print(log, level, "%s%s%s", fprefix, buffer, postfix);
608
0
  free(buffer);
609
0
  free(fprefix);
610
0
}
611
612
static void smartcard_log_redir_handle(wLog* log, const REDIR_SCARDHANDLE* pHandle)
613
0
{
614
0
  WINPR_ASSERT(pHandle);
615
0
  smartcard_dump_array(log, g_LogLevel, "handle: ", "", pHandle->pbHandle, pHandle->cbHandle);
616
0
}
617
618
static void smartcard_log_context(wLog* log, const REDIR_SCARDCONTEXT* phContext)
619
0
{
620
0
  WINPR_ASSERT(phContext);
621
0
  smartcard_dump_array(log, g_LogLevel, "hContext: ", "", phContext->pbContext,
622
0
                       phContext->cbContext);
623
0
}
624
625
static void smartcard_trace_context_and_string_call_a(wLog* log, const char* name,
626
                                                      const REDIR_SCARDCONTEXT* phContext,
627
                                                      const CHAR* sz)
628
0
{
629
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
630
0
    return;
631
632
0
  WLog_Print(log, g_LogLevel, "%s {", name);
633
0
  smartcard_log_context(log, phContext);
634
0
  WLog_Print(log, g_LogLevel, "  sz=%s", sz);
635
636
0
  WLog_Print(log, g_LogLevel, "}");
637
0
}
638
639
static void smartcard_trace_context_and_string_call_w(wLog* log, const char* name,
640
                                                      const REDIR_SCARDCONTEXT* phContext,
641
                                                      const WCHAR* sz)
642
0
{
643
0
  char* tmp = nullptr;
644
645
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
646
0
    return;
647
648
0
  if (sz)
649
0
    tmp = ConvertWCharToUtf8Alloc(sz, nullptr);
650
651
0
  WLog_Print(log, g_LogLevel, "%s {", name);
652
0
  smartcard_log_context(log, phContext);
653
0
  WLog_Print(log, g_LogLevel, "  sz=%s", tmp);
654
0
  WLog_Print(log, g_LogLevel, "}");
655
0
  free(tmp);
656
0
}
657
658
static void smartcard_trace_context_call(wLog* log, const Context_Call* call, const char* name)
659
0
{
660
0
  WINPR_ASSERT(call);
661
662
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
663
0
    return;
664
665
0
  WLog_Print(log, g_LogLevel, "%s_Call {", name);
666
0
  smartcard_log_context(log, &call->handles.hContext);
667
668
0
  WLog_Print(log, g_LogLevel, "}");
669
0
}
670
671
static void smartcard_trace_list_reader_groups_call(wLog* log, const ListReaderGroups_Call* call,
672
                                                    BOOL unicode)
673
0
{
674
0
  WINPR_ASSERT(call);
675
676
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
677
0
    return;
678
679
0
  WLog_Print(log, g_LogLevel, "ListReaderGroups%s_Call {", unicode ? "W" : "A");
680
0
  smartcard_log_context(log, &call->handles.hContext);
681
682
0
  WLog_Print(log, g_LogLevel, "fmszGroupsIsNULL: %" PRId32 " cchGroups: 0x%08" PRIx32,
683
0
             call->fmszGroupsIsNULL, call->cchGroups);
684
0
  WLog_Print(log, g_LogLevel, "}");
685
0
}
686
687
static void dump_reader_states_return(wLog* log, const ReaderState_Return* rgReaderStates,
688
                                      UINT32 cReaders)
689
0
{
690
0
  WINPR_ASSERT(rgReaderStates || (cReaders == 0));
691
0
  for (UINT32 index = 0; index < cReaders; index++)
692
0
  {
693
0
    const ReaderState_Return* readerState = &rgReaderStates[index];
694
0
    char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
695
0
    char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
696
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
697
0
               szCurrentState, readerState->dwCurrentState);
698
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
699
0
               szEventState, readerState->dwEventState);
700
0
    free(szCurrentState);
701
0
    free(szEventState);
702
703
0
    smartcard_dump_array(log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { ", " }",
704
0
                         readerState->rgbAtr, readerState->cbAtr, index, readerState->cbAtr);
705
0
  }
706
0
}
707
708
static void dump_reader_states_a(wLog* log, const SCARD_READERSTATEA* rgReaderStates,
709
                                 UINT32 cReaders)
710
0
{
711
0
  WINPR_ASSERT(rgReaderStates || (cReaders == 0));
712
0
  for (UINT32 index = 0; index < cReaders; index++)
713
0
  {
714
0
    const SCARD_READERSTATEA* readerState = &rgReaderStates[index];
715
716
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: szReader: %s cbAtr: %" PRIu32 "", index,
717
0
               readerState->szReader, readerState->cbAtr);
718
0
    char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
719
0
    char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
720
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
721
0
               szCurrentState, readerState->dwCurrentState);
722
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
723
0
               szEventState, readerState->dwEventState);
724
0
    free(szCurrentState);
725
0
    free(szEventState);
726
727
0
    smartcard_dump_array(log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { ", " }",
728
0
                         readerState->rgbAtr, readerState->cbAtr, index, readerState->cbAtr);
729
0
  }
730
0
}
731
732
static void dump_reader_states_w(wLog* log, const SCARD_READERSTATEW* rgReaderStates,
733
                                 UINT32 cReaders)
734
0
{
735
0
  WINPR_ASSERT(rgReaderStates || (cReaders == 0));
736
0
  for (UINT32 index = 0; index < cReaders; index++)
737
0
  {
738
0
    const SCARD_READERSTATEW* readerState = &rgReaderStates[index];
739
0
    char* buffer = ConvertWCharToUtf8Alloc(readerState->szReader, nullptr);
740
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: szReader: %s cbAtr: %" PRIu32 "", index,
741
0
               buffer, readerState->cbAtr);
742
0
    free(buffer);
743
0
    char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
744
0
    char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
745
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
746
0
               szCurrentState, readerState->dwCurrentState);
747
0
    WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
748
0
               szEventState, readerState->dwEventState);
749
0
    free(szCurrentState);
750
0
    free(szEventState);
751
752
0
    smartcard_dump_array(log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { ", " }",
753
0
                         readerState->rgbAtr, readerState->cbAtr, index, readerState->cbAtr);
754
0
  }
755
0
}
756
757
static void smartcard_trace_get_status_change_w_call(wLog* log, const GetStatusChangeW_Call* call)
758
0
{
759
0
  WINPR_ASSERT(call);
760
761
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
762
0
    return;
763
764
0
  WLog_Print(log, g_LogLevel, "GetStatusChangeW_Call {");
765
0
  smartcard_log_context(log, &call->handles.hContext);
766
767
0
  WLog_Print(log, g_LogLevel, "dwTimeOut: 0x%08" PRIX32 " cReaders: %" PRIu32 "", call->dwTimeOut,
768
0
             call->cReaders);
769
770
0
  dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
771
772
0
  WLog_Print(log, g_LogLevel, "}");
773
0
}
774
775
static void smartcard_trace_list_reader_groups_return(wLog* log, const ListReaderGroups_Return* ret,
776
                                                      BOOL unicode)
777
0
{
778
0
  WINPR_ASSERT(ret);
779
780
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
781
0
    return;
782
783
0
  char* mszA = smartcard_convert_string_list(ret->msz, ret->cBytes, unicode);
784
785
0
  WLog_Print(log, g_LogLevel, "ListReaderGroups%s_Return {", unicode ? "W" : "A");
786
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIx32 ")",
787
0
             SCardGetErrorString(ret->ReturnCode),
788
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
789
0
  WLog_Print(log, g_LogLevel, "  cBytes: %" PRIu32 " msz: %s", ret->cBytes, mszA);
790
0
  WLog_Print(log, g_LogLevel, "}");
791
0
  free(mszA);
792
0
}
793
794
static void smartcard_trace_list_readers_call(wLog* log, const ListReaders_Call* call, BOOL unicode)
795
0
{
796
0
  WINPR_ASSERT(call);
797
798
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
799
0
    return;
800
801
0
  char* mszGroupsA = smartcard_convert_string_list(call->mszGroups, call->cBytes, unicode);
802
803
0
  WLog_Print(log, g_LogLevel, "ListReaders%s_Call {", unicode ? "W" : "A");
804
0
  smartcard_log_context(log, &call->handles.hContext);
805
806
0
  WLog_Print(log, g_LogLevel,
807
0
             "cBytes: %" PRIu32 " mszGroups: %s fmszReadersIsNULL: %" PRId32
808
0
             " cchReaders: 0x%08" PRIX32 "",
809
0
             call->cBytes, mszGroupsA, call->fmszReadersIsNULL, call->cchReaders);
810
0
  WLog_Print(log, g_LogLevel, "}");
811
812
0
  free(mszGroupsA);
813
0
}
814
815
static void smartcard_trace_locate_cards_by_atr_a_call(wLog* log,
816
                                                       const LocateCardsByATRA_Call* call)
817
0
{
818
0
  WINPR_ASSERT(call);
819
820
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
821
0
    return;
822
823
0
  WLog_Print(log, g_LogLevel, "LocateCardsByATRA_Call {");
824
0
  smartcard_log_context(log, &call->handles.hContext);
825
826
0
  dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
827
828
0
  WLog_Print(log, g_LogLevel, "}");
829
0
}
830
831
static void smartcard_trace_locate_cards_a_call(wLog* log, const LocateCardsA_Call* call)
832
0
{
833
0
  WINPR_ASSERT(call);
834
835
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
836
0
    return;
837
838
0
  WLog_Print(log, g_LogLevel, "LocateCardsA_Call {");
839
0
  smartcard_log_context(log, &call->handles.hContext);
840
0
  WLog_Print(log, g_LogLevel, " cBytes=%" PRIu32, call->cBytes);
841
0
  smartcard_msz_dump(log, g_LogLevel, " mszCards=", call->mszCards, call->cBytes, FALSE);
842
0
  WLog_Print(log, g_LogLevel, " cReaders=%" PRIu32, call->cReaders);
843
0
  dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
844
845
0
  WLog_Print(log, g_LogLevel, "}");
846
0
}
847
848
static void smartcard_trace_locate_cards_return(wLog* log, const LocateCards_Return* ret)
849
0
{
850
0
  WINPR_ASSERT(ret);
851
852
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
853
0
    return;
854
855
0
  WLog_Print(log, g_LogLevel, "LocateCards_Return {");
856
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
857
0
             SCardGetErrorString(ret->ReturnCode),
858
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
859
860
0
  if (ret->ReturnCode == SCARD_S_SUCCESS)
861
0
  {
862
0
    WLog_Print(log, g_LogLevel, "  cReaders=%" PRIu32, ret->cReaders);
863
0
  }
864
0
  WLog_Print(log, g_LogLevel, "}");
865
0
}
866
867
static void smartcard_trace_get_reader_icon_return(wLog* log, const GetReaderIcon_Return* ret)
868
0
{
869
0
  WINPR_ASSERT(ret);
870
871
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
872
0
    return;
873
874
0
  WLog_Print(log, g_LogLevel, "GetReaderIcon_Return {");
875
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
876
0
             SCardGetErrorString(ret->ReturnCode),
877
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
878
879
0
  if (ret->ReturnCode == SCARD_S_SUCCESS)
880
0
  {
881
0
    WLog_Print(log, g_LogLevel, "  cbDataLen=%" PRIu32, ret->cbDataLen);
882
0
  }
883
0
  WLog_Print(log, g_LogLevel, "}");
884
0
}
885
886
static void smartcard_trace_get_transmit_count_return(wLog* log, const GetTransmitCount_Return* ret)
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, "GetTransmitCount_Return {");
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
898
0
  WLog_Print(log, g_LogLevel, "  cTransmitCount=%" PRIu32, ret->cTransmitCount);
899
0
  WLog_Print(log, g_LogLevel, "}");
900
0
}
901
902
static void smartcard_trace_read_cache_return(wLog* log, const ReadCache_Return* ret)
903
0
{
904
0
  WINPR_ASSERT(ret);
905
906
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
907
0
    return;
908
909
0
  WLog_Print(log, g_LogLevel, "ReadCache_Return {");
910
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
911
0
             SCardGetErrorString(ret->ReturnCode),
912
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
913
914
0
  if (ret->ReturnCode == SCARD_S_SUCCESS)
915
0
  {
916
0
    WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, ret->cbDataLen);
917
0
    smartcard_dump_array(log, g_LogLevel, "  cbData: ", "", ret->pbData, ret->cbDataLen);
918
0
  }
919
0
  WLog_Print(log, g_LogLevel, "}");
920
0
}
921
922
static void smartcard_trace_locate_cards_w_call(wLog* log, const LocateCardsW_Call* call)
923
0
{
924
0
  WINPR_ASSERT(call);
925
926
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
927
0
    return;
928
929
0
  WLog_Print(log, g_LogLevel, "LocateCardsW_Call {");
930
0
  smartcard_log_context(log, &call->handles.hContext);
931
0
  WLog_Print(log, g_LogLevel, " cBytes=%" PRIu32, call->cBytes);
932
0
  smartcard_msz_dump(log, g_LogLevel, " sz2=", call->mszCards, call->cBytes, TRUE);
933
0
  WLog_Print(log, g_LogLevel, " cReaders=%" PRIu32, call->cReaders);
934
0
  dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
935
0
  WLog_Print(log, g_LogLevel, "}");
936
0
}
937
938
static void smartcard_trace_list_readers_return(wLog* log, const ListReaders_Return* ret,
939
                                                BOOL unicode)
940
0
{
941
0
  WINPR_ASSERT(ret);
942
943
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
944
0
    return;
945
946
0
  WLog_Print(log, g_LogLevel, "ListReaders%s_Return {", unicode ? "W" : "A");
947
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
948
0
             SCardGetErrorString(ret->ReturnCode),
949
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
950
951
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
952
0
  {
953
0
    WLog_Print(log, g_LogLevel, "}");
954
0
    return;
955
0
  }
956
957
0
  char* mszA = smartcard_convert_string_list(ret->msz, ret->cBytes, unicode);
958
959
0
  WLog_Print(log, g_LogLevel, "  cBytes: %" PRIu32 " msz: %s", ret->cBytes, mszA);
960
0
  WLog_Print(log, g_LogLevel, "}");
961
0
  free(mszA);
962
0
}
963
964
static void smartcard_trace_get_status_change_return(wLog* log, const GetStatusChange_Return* ret,
965
                                                     BOOL unicode)
966
0
{
967
0
  WINPR_ASSERT(ret);
968
969
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
970
0
    return;
971
972
0
  WLog_Print(log, g_LogLevel, "GetStatusChange%s_Return {", unicode ? "W" : "A");
973
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
974
0
             SCardGetErrorString(ret->ReturnCode),
975
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
976
0
  WLog_Print(log, g_LogLevel, "  cReaders: %" PRIu32 "", ret->cReaders);
977
978
0
  dump_reader_states_return(log, ret->rgReaderStates, ret->cReaders);
979
980
0
  if (!ret->rgReaderStates && (ret->cReaders > 0))
981
0
  {
982
0
    WLog_Print(log, g_LogLevel, "    [INVALID STATE] rgReaderStates=nullptr, cReaders=%" PRIu32,
983
0
               ret->cReaders);
984
0
  }
985
0
  else if (ret->ReturnCode != SCARD_S_SUCCESS)
986
0
  {
987
0
    WLog_Print(log, g_LogLevel, "    [INVALID RETURN] rgReaderStates, cReaders=%" PRIu32,
988
0
               ret->cReaders);
989
0
  }
990
0
  else
991
0
  {
992
0
    for (UINT32 index = 0; index < ret->cReaders; index++)
993
0
    {
994
0
      const ReaderState_Return* rgReaderState = &(ret->rgReaderStates[index]);
995
0
      char* szCurrentState = SCardGetReaderStateString(rgReaderState->dwCurrentState);
996
0
      char* szEventState = SCardGetReaderStateString(rgReaderState->dwEventState);
997
0
      WLog_Print(log, g_LogLevel, "    [%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")",
998
0
                 index, szCurrentState, rgReaderState->dwCurrentState);
999
0
      WLog_Print(log, g_LogLevel, "    [%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")",
1000
0
                 index, szEventState, rgReaderState->dwEventState);
1001
0
      smartcard_dump_array(
1002
0
          log, g_LogLevel, "    [%" PRIu32 "]: cbAtr: %" PRIu32 " rgbAtr: ", "",
1003
0
          rgReaderState->rgbAtr, rgReaderState->cbAtr, index, rgReaderState->cbAtr);
1004
0
      free(szCurrentState);
1005
0
      free(szEventState);
1006
0
    }
1007
0
  }
1008
1009
0
  WLog_Print(log, g_LogLevel, "}");
1010
0
}
1011
1012
static void smartcard_trace_context_and_two_strings_a_call(wLog* log,
1013
                                                           const ContextAndTwoStringA_Call* call)
1014
0
{
1015
0
  WINPR_ASSERT(call);
1016
1017
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1018
0
    return;
1019
1020
0
  WLog_Print(log, g_LogLevel, "ContextAndTwoStringW_Call {");
1021
0
  smartcard_log_context(log, &call->handles.hContext);
1022
0
  WLog_Print(log, g_LogLevel, " sz1=%s", call->sz1);
1023
0
  WLog_Print(log, g_LogLevel, " sz2=%s", call->sz2);
1024
0
  WLog_Print(log, g_LogLevel, "}");
1025
0
}
1026
1027
static void smartcard_trace_context_and_two_strings_w_call(wLog* log,
1028
                                                           const ContextAndTwoStringW_Call* call)
1029
0
{
1030
0
  WINPR_ASSERT(call);
1031
0
  char sz1[1024] = WINPR_C_ARRAY_INIT;
1032
0
  char sz2[1024] = WINPR_C_ARRAY_INIT;
1033
1034
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1035
0
    return;
1036
0
  if (call->sz1)
1037
0
    (void)ConvertWCharToUtf8(call->sz1, sz1, ARRAYSIZE(sz1));
1038
0
  if (call->sz2)
1039
0
    (void)ConvertWCharToUtf8(call->sz2, sz2, ARRAYSIZE(sz2));
1040
1041
0
  WLog_Print(log, g_LogLevel, "ContextAndTwoStringW_Call {");
1042
0
  smartcard_log_context(log, &call->handles.hContext);
1043
0
  WLog_Print(log, g_LogLevel, " sz1=%s", sz1);
1044
0
  WLog_Print(log, g_LogLevel, " sz2=%s", sz2);
1045
0
  WLog_Print(log, g_LogLevel, "}");
1046
0
}
1047
1048
static void smartcard_trace_get_transmit_count_call(wLog* log, const GetTransmitCount_Call* call)
1049
0
{
1050
0
  WINPR_ASSERT(call);
1051
1052
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1053
0
    return;
1054
1055
0
  WLog_Print(log, g_LogLevel, "GetTransmitCount_Call {");
1056
0
  smartcard_log_context(log, &call->handles.hContext);
1057
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1058
1059
0
  WLog_Print(log, g_LogLevel, "}");
1060
0
}
1061
1062
static void smartcard_trace_write_cache_a_call(wLog* log, const WriteCacheA_Call* call)
1063
0
{
1064
0
  WINPR_ASSERT(call);
1065
1066
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1067
0
    return;
1068
1069
0
  WLog_Print(log, g_LogLevel, "WriteCacheA_Call {");
1070
1071
0
  WLog_Print(log, g_LogLevel, "  szLookupName=%s", call->szLookupName);
1072
1073
0
  smartcard_log_context(log, &call->Common.handles.hContext);
1074
0
  smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1075
0
                       sizeof(UUID));
1076
0
  WLog_Print(log, g_LogLevel, "  FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1077
0
  WLog_Print(log, g_LogLevel, "  cbDataLen=%" PRIu32, call->Common.cbDataLen);
1078
0
  smartcard_dump_array(log, g_LogLevel, "  pbData=", "", call->Common.pbData,
1079
0
                       call->Common.cbDataLen);
1080
0
  WLog_Print(log, g_LogLevel, "}");
1081
0
}
1082
1083
static void smartcard_trace_write_cache_w_call(wLog* log, const WriteCacheW_Call* call)
1084
0
{
1085
0
  WINPR_ASSERT(call);
1086
0
  char tmp[1024] = WINPR_C_ARRAY_INIT;
1087
1088
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1089
0
    return;
1090
1091
0
  WLog_Print(log, g_LogLevel, "WriteCacheW_Call {");
1092
1093
0
  if (call->szLookupName)
1094
0
    (void)ConvertWCharToUtf8(call->szLookupName, tmp, ARRAYSIZE(tmp));
1095
0
  WLog_Print(log, g_LogLevel, "  szLookupName=%s", tmp);
1096
1097
0
  smartcard_log_context(log, &call->Common.handles.hContext);
1098
0
  smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1099
0
                       sizeof(UUID));
1100
0
  WLog_Print(log, g_LogLevel, "  FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1101
0
  WLog_Print(log, g_LogLevel, "  cbDataLen=%" PRIu32, call->Common.cbDataLen);
1102
0
  smartcard_dump_array(log, g_LogLevel, "  pbData=", "", call->Common.pbData,
1103
0
                       call->Common.cbDataLen);
1104
0
  WLog_Print(log, g_LogLevel, "}");
1105
0
}
1106
1107
static void smartcard_trace_read_cache_a_call(wLog* log, const ReadCacheA_Call* call)
1108
0
{
1109
0
  WINPR_ASSERT(call);
1110
1111
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1112
0
    return;
1113
1114
0
  WLog_Print(log, g_LogLevel, "ReadCacheA_Call {");
1115
1116
0
  WLog_Print(log, g_LogLevel, "  szLookupName=%s", call->szLookupName);
1117
0
  smartcard_log_context(log, &call->Common.handles.hContext);
1118
0
  smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1119
0
                       sizeof(UUID));
1120
0
  WLog_Print(log, g_LogLevel, "  FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1121
0
  WLog_Print(log, g_LogLevel, "  fPbDataIsNULL=%" PRId32, call->Common.fPbDataIsNULL);
1122
0
  WLog_Print(log, g_LogLevel, "  cbDataLen=%" PRIu32, call->Common.cbDataLen);
1123
1124
0
  WLog_Print(log, g_LogLevel, "}");
1125
0
}
1126
1127
static void smartcard_trace_read_cache_w_call(wLog* log, const ReadCacheW_Call* call)
1128
0
{
1129
0
  WINPR_ASSERT(call);
1130
0
  char tmp[1024] = WINPR_C_ARRAY_INIT;
1131
1132
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1133
0
    return;
1134
1135
0
  WLog_Print(log, g_LogLevel, "ReadCacheW_Call {");
1136
0
  if (call->szLookupName)
1137
0
    (void)ConvertWCharToUtf8(call->szLookupName, tmp, ARRAYSIZE(tmp));
1138
0
  WLog_Print(log, g_LogLevel, "  szLookupName=%s", tmp);
1139
1140
0
  smartcard_log_context(log, &call->Common.handles.hContext);
1141
0
  smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1142
0
                       sizeof(UUID));
1143
0
  WLog_Print(log, g_LogLevel, "  FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1144
0
  WLog_Print(log, g_LogLevel, "  fPbDataIsNULL=%" PRId32, call->Common.fPbDataIsNULL);
1145
0
  WLog_Print(log, g_LogLevel, "  cbDataLen=%" PRIu32, call->Common.cbDataLen);
1146
1147
0
  WLog_Print(log, g_LogLevel, "}");
1148
0
}
1149
1150
static void smartcard_trace_transmit_call(wLog* log, const Transmit_Call* call)
1151
0
{
1152
0
  WINPR_ASSERT(call);
1153
0
  UINT32 cbExtraBytes = 0;
1154
0
  BYTE* pbExtraBytes = nullptr;
1155
1156
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1157
0
    return;
1158
1159
0
  WLog_Print(log, g_LogLevel, "Transmit_Call {");
1160
0
  smartcard_log_context(log, &call->handles.hContext);
1161
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1162
1163
0
  if (call->pioSendPci)
1164
0
  {
1165
0
    cbExtraBytes = (UINT32)(call->pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1166
0
    pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
1167
0
    WLog_Print(log, g_LogLevel, "pioSendPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1168
0
               call->pioSendPci->dwProtocol, cbExtraBytes);
1169
1170
0
    if (cbExtraBytes)
1171
0
    {
1172
0
      smartcard_dump_array(log, g_LogLevel, "pbExtraBytes: ", "", pbExtraBytes, cbExtraBytes);
1173
0
    }
1174
0
  }
1175
0
  else
1176
0
  {
1177
0
    WLog_Print(log, g_LogLevel, "pioSendPci: null");
1178
0
  }
1179
1180
0
  WLog_Print(log, g_LogLevel, "cbSendLength: %" PRIu32 "", call->cbSendLength);
1181
1182
0
  if (call->pbSendBuffer)
1183
0
  {
1184
0
    smartcard_dump_array(log, g_LogLevel, "pbSendBuffer: ", "", call->pbSendBuffer,
1185
0
                         call->cbSendLength);
1186
0
  }
1187
0
  else
1188
0
  {
1189
0
    WLog_Print(log, g_LogLevel, "pbSendBuffer: null");
1190
0
  }
1191
1192
0
  if (call->pioRecvPci)
1193
0
  {
1194
0
    cbExtraBytes = (UINT32)(call->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1195
0
    pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
1196
0
    WLog_Print(log, g_LogLevel, "pioRecvPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1197
0
               call->pioRecvPci->dwProtocol, cbExtraBytes);
1198
1199
0
    if (cbExtraBytes)
1200
0
    {
1201
0
      smartcard_dump_array(log, g_LogLevel, "pbExtraBytes: ", "", pbExtraBytes, cbExtraBytes);
1202
0
    }
1203
0
  }
1204
0
  else
1205
0
  {
1206
0
    WLog_Print(log, g_LogLevel, "pioRecvPci: null");
1207
0
  }
1208
1209
0
  WLog_Print(log, g_LogLevel, "fpbRecvBufferIsNULL: %" PRId32 " cbRecvLength: %" PRIu32 "",
1210
0
             call->fpbRecvBufferIsNULL, call->cbRecvLength);
1211
0
  WLog_Print(log, g_LogLevel, "}");
1212
0
}
1213
1214
static void smartcard_trace_locate_cards_by_atr_w_call(wLog* log,
1215
                                                       const LocateCardsByATRW_Call* call)
1216
0
{
1217
0
  WINPR_ASSERT(call);
1218
1219
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1220
0
    return;
1221
1222
0
  WLog_Print(log, g_LogLevel, "LocateCardsByATRW_Call {");
1223
0
  smartcard_log_context(log, &call->handles.hContext);
1224
1225
0
  dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
1226
1227
0
  WLog_Print(log, g_LogLevel, "}");
1228
0
}
1229
1230
static void smartcard_trace_transmit_return(wLog* log, const Transmit_Return* ret)
1231
0
{
1232
0
  WINPR_ASSERT(ret);
1233
0
  UINT32 cbExtraBytes = 0;
1234
0
  BYTE* pbExtraBytes = nullptr;
1235
1236
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1237
0
    return;
1238
1239
0
  WLog_Print(log, g_LogLevel, "Transmit_Return {");
1240
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1241
0
             SCardGetErrorString(ret->ReturnCode),
1242
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1243
1244
0
  if (ret->pioRecvPci)
1245
0
  {
1246
0
    cbExtraBytes = (UINT32)(ret->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1247
0
    pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
1248
0
    WLog_Print(log, g_LogLevel,
1249
0
               "  pioRecvPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1250
0
               ret->pioRecvPci->dwProtocol, cbExtraBytes);
1251
1252
0
    if (cbExtraBytes)
1253
0
    {
1254
0
      smartcard_dump_array(log, g_LogLevel, "  pbExtraBytes: ", "", pbExtraBytes,
1255
0
                           cbExtraBytes);
1256
0
    }
1257
0
  }
1258
0
  else
1259
0
  {
1260
0
    WLog_Print(log, g_LogLevel, "  pioRecvPci: null");
1261
0
  }
1262
1263
0
  WLog_Print(log, g_LogLevel, "  cbRecvLength: %" PRIu32 "", ret->cbRecvLength);
1264
1265
0
  if (ret->pbRecvBuffer)
1266
0
  {
1267
0
    smartcard_dump_array(log, g_LogLevel, "  pbRecvBuffer: ", "", ret->pbRecvBuffer,
1268
0
                         ret->cbRecvLength);
1269
0
  }
1270
0
  else
1271
0
  {
1272
0
    WLog_Print(log, g_LogLevel, "  pbRecvBuffer: null");
1273
0
  }
1274
1275
0
  WLog_Print(log, g_LogLevel, "}");
1276
0
}
1277
1278
static void smartcard_trace_control_return(wLog* log, const Control_Return* ret)
1279
0
{
1280
0
  WINPR_ASSERT(ret);
1281
1282
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1283
0
    return;
1284
1285
0
  WLog_Print(log, g_LogLevel, "Control_Return {");
1286
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1287
0
             SCardGetErrorString(ret->ReturnCode),
1288
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1289
0
  WLog_Print(log, g_LogLevel, "  cbOutBufferSize: %" PRIu32 "", ret->cbOutBufferSize);
1290
1291
0
  if (ret->pvOutBuffer)
1292
0
  {
1293
0
    smartcard_dump_array(log, g_LogLevel, "pvOutBuffer: ", "", ret->pvOutBuffer,
1294
0
                         ret->cbOutBufferSize);
1295
0
  }
1296
0
  else
1297
0
  {
1298
0
    WLog_Print(log, g_LogLevel, "pvOutBuffer: null");
1299
0
  }
1300
1301
0
  WLog_Print(log, g_LogLevel, "}");
1302
0
}
1303
1304
static void smartcard_trace_control_call(wLog* log, const Control_Call* call)
1305
0
{
1306
0
  WINPR_ASSERT(call);
1307
1308
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1309
0
    return;
1310
1311
0
  WLog_Print(log, g_LogLevel, "Control_Call {");
1312
0
  smartcard_log_context(log, &call->handles.hContext);
1313
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1314
1315
0
  WLog_Print(log, g_LogLevel,
1316
0
             "dwControlCode: 0x%08" PRIX32 " cbInBufferSize: %" PRIu32
1317
0
             " fpvOutBufferIsNULL: %" PRId32 " cbOutBufferSize: %" PRIu32 "",
1318
0
             call->dwControlCode, call->cbInBufferSize, call->fpvOutBufferIsNULL,
1319
0
             call->cbOutBufferSize);
1320
1321
0
  if (call->pvInBuffer)
1322
0
  {
1323
0
    smartcard_dump_array(log, WLOG_DEBUG, "pbInBuffer: ", "", call->pvInBuffer,
1324
0
                         call->cbInBufferSize);
1325
0
  }
1326
0
  else
1327
0
  {
1328
0
    WLog_Print(log, g_LogLevel, "pvInBuffer: null");
1329
0
  }
1330
1331
0
  WLog_Print(log, g_LogLevel, "}");
1332
0
}
1333
1334
static void smartcard_trace_set_attrib_call(wLog* log, const SetAttrib_Call* call)
1335
0
{
1336
0
  WINPR_ASSERT(call);
1337
1338
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1339
0
    return;
1340
1341
0
  WLog_Print(log, g_LogLevel, "GetAttrib_Call {");
1342
0
  smartcard_log_context(log, &call->handles.hContext);
1343
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1344
0
  WLog_Print(log, g_LogLevel, "dwAttrId: 0x%08" PRIX32, call->dwAttrId);
1345
0
  WLog_Print(log, g_LogLevel, "cbAttrLen: 0x%08" PRIx32, call->cbAttrLen);
1346
0
  smartcard_dump_array(log, g_LogLevel, "pbAttr: ", "", call->pbAttr, call->cbAttrLen);
1347
0
  WLog_Print(log, g_LogLevel, "}");
1348
0
}
1349
1350
static void smartcard_trace_get_attrib_return(wLog* log, const GetAttrib_Return* ret,
1351
                                              DWORD dwAttrId)
1352
0
{
1353
0
  WINPR_ASSERT(ret);
1354
1355
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1356
0
    return;
1357
1358
0
  WLog_Print(log, g_LogLevel, "GetAttrib_Return {");
1359
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1360
0
             SCardGetErrorString(ret->ReturnCode),
1361
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1362
0
  WLog_Print(log, g_LogLevel, "  dwAttrId: %s (0x%08" PRIX32 ") cbAttrLen: 0x%08" PRIX32 "",
1363
0
             SCardGetAttributeString(dwAttrId), dwAttrId, ret->cbAttrLen);
1364
0
  smartcard_dump_array(log, g_LogLevel, "  ", "", ret->pbAttr, ret->cbAttrLen);
1365
1366
0
  WLog_Print(log, g_LogLevel, "}");
1367
0
}
1368
1369
static void smartcard_trace_get_attrib_call(wLog* log, const GetAttrib_Call* call)
1370
0
{
1371
0
  WINPR_ASSERT(call);
1372
1373
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1374
0
    return;
1375
1376
0
  WLog_Print(log, g_LogLevel, "GetAttrib_Call {");
1377
0
  smartcard_log_context(log, &call->handles.hContext);
1378
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1379
1380
0
  WLog_Print(log, g_LogLevel,
1381
0
             "dwAttrId: %s (0x%08" PRIX32 ") fpbAttrIsNULL: %" PRId32 " cbAttrLen: 0x%08" PRIX32
1382
0
             "",
1383
0
             SCardGetAttributeString(call->dwAttrId), call->dwAttrId, call->fpbAttrIsNULL,
1384
0
             call->cbAttrLen);
1385
0
  WLog_Print(log, g_LogLevel, "}");
1386
0
}
1387
1388
static void smartcard_trace_status_call(wLog* log, const Status_Call* call, BOOL unicode)
1389
0
{
1390
0
  WINPR_ASSERT(call);
1391
1392
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1393
0
    return;
1394
1395
0
  WLog_Print(log, g_LogLevel, "Status%s_Call {", unicode ? "W" : "A");
1396
0
  smartcard_log_context(log, &call->handles.hContext);
1397
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1398
1399
0
  WLog_Print(log, g_LogLevel,
1400
0
             "fmszReaderNamesIsNULL: %" PRId32 " cchReaderLen: %" PRIu32 " cbAtrLen: %" PRIu32 "",
1401
0
             call->fmszReaderNamesIsNULL, call->cchReaderLen, call->cbAtrLen);
1402
0
  WLog_Print(log, g_LogLevel, "}");
1403
0
}
1404
1405
static void smartcard_trace_status_return(wLog* log, const Status_Return* ret, BOOL unicode)
1406
0
{
1407
0
  WINPR_ASSERT(ret);
1408
0
  char* mszReaderNamesA = nullptr;
1409
0
  UINT32 cBytes = 0;
1410
1411
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1412
0
    return;
1413
0
  cBytes = ret->cBytes;
1414
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
1415
0
    cBytes = 0;
1416
0
  if (cBytes == SCARD_AUTOALLOCATE)
1417
0
    cBytes = 0;
1418
0
  mszReaderNamesA = smartcard_convert_string_list(ret->mszReaderNames, cBytes, unicode);
1419
1420
0
  WLog_Print(log, g_LogLevel, "Status%s_Return {", unicode ? "W" : "A");
1421
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1422
0
             SCardGetErrorString(ret->ReturnCode),
1423
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1424
0
  WLog_Print(log, g_LogLevel, "  dwState: %s (0x%08" PRIX32 ") dwProtocol: %s (0x%08" PRIX32 ")",
1425
0
             SCardGetCardStateString(ret->dwState), ret->dwState,
1426
0
             SCardGetProtocolString(ret->dwProtocol), ret->dwProtocol);
1427
1428
0
  WLog_Print(log, g_LogLevel, "  cBytes: %" PRIu32 " mszReaderNames: %s", ret->cBytes,
1429
0
             mszReaderNamesA);
1430
1431
0
  smartcard_dump_array(log, g_LogLevel, "  cbAtrLen: %" PRIu32 " pbAtr: ", "", ret->pbAtr,
1432
0
                       ret->cbAtrLen, ret->cbAtrLen);
1433
0
  WLog_Print(log, g_LogLevel, "}");
1434
0
  free(mszReaderNamesA);
1435
0
}
1436
1437
static void smartcard_trace_state_return(wLog* log, const State_Return* ret)
1438
0
{
1439
0
  WINPR_ASSERT(ret);
1440
0
  char* state = nullptr;
1441
1442
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1443
0
    return;
1444
1445
0
  state = SCardGetReaderStateString(ret->dwState);
1446
0
  WLog_Print(log, g_LogLevel, "Reconnect_Return {");
1447
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1448
0
             SCardGetErrorString(ret->ReturnCode),
1449
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1450
0
  WLog_Print(log, g_LogLevel, "  dwState:    %s (0x%08" PRIX32 ")", state, ret->dwState);
1451
0
  WLog_Print(log, g_LogLevel, "  dwProtocol: %s (0x%08" PRIX32 ")",
1452
0
             SCardGetProtocolString(ret->dwProtocol), ret->dwProtocol);
1453
0
  WLog_Print(log, g_LogLevel, "  cbAtrLen:      (0x%08" PRIX32 ")", ret->cbAtrLen);
1454
0
  smartcard_dump_array(log, g_LogLevel, "  rgAtr:      ", "", ret->rgAtr, sizeof(ret->rgAtr));
1455
0
  WLog_Print(log, g_LogLevel, "}");
1456
0
  free(state);
1457
0
}
1458
1459
static void smartcard_trace_reconnect_return(wLog* log, const Reconnect_Return* ret)
1460
0
{
1461
0
  WINPR_ASSERT(ret);
1462
1463
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1464
0
    return;
1465
1466
0
  WLog_Print(log, g_LogLevel, "Reconnect_Return {");
1467
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1468
0
             SCardGetErrorString(ret->ReturnCode),
1469
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1470
0
  WLog_Print(log, g_LogLevel, "  dwActiveProtocol: %s (0x%08" PRIX32 ")",
1471
0
             SCardGetProtocolString(ret->dwActiveProtocol), ret->dwActiveProtocol);
1472
0
  WLog_Print(log, g_LogLevel, "}");
1473
0
}
1474
1475
static void smartcard_trace_connect_a_call(wLog* log, const ConnectA_Call* call)
1476
0
{
1477
0
  WINPR_ASSERT(call);
1478
1479
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1480
0
    return;
1481
1482
0
  WLog_Print(log, g_LogLevel, "ConnectA_Call {");
1483
0
  smartcard_log_context(log, &call->Common.handles.hContext);
1484
1485
0
  WLog_Print(log, g_LogLevel,
1486
0
             "szReader: %s dwShareMode: %s (0x%08" PRIX32
1487
0
             ") dwPreferredProtocols: %s (0x%08" PRIX32 ")",
1488
0
             call->szReader, SCardGetShareModeString(call->Common.dwShareMode),
1489
0
             call->Common.dwShareMode, SCardGetProtocolString(call->Common.dwPreferredProtocols),
1490
0
             call->Common.dwPreferredProtocols);
1491
0
  WLog_Print(log, g_LogLevel, "}");
1492
0
}
1493
1494
static void smartcard_trace_connect_w_call(wLog* log, const ConnectW_Call* call)
1495
0
{
1496
0
  WINPR_ASSERT(call);
1497
0
  char szReaderA[1024] = WINPR_C_ARRAY_INIT;
1498
1499
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1500
0
    return;
1501
1502
0
  if (call->szReader)
1503
0
    (void)ConvertWCharToUtf8(call->szReader, szReaderA, ARRAYSIZE(szReaderA));
1504
0
  WLog_Print(log, g_LogLevel, "ConnectW_Call {");
1505
0
  smartcard_log_context(log, &call->Common.handles.hContext);
1506
1507
0
  WLog_Print(log, g_LogLevel,
1508
0
             "szReader: %s dwShareMode: %s (0x%08" PRIX32
1509
0
             ") dwPreferredProtocols: %s (0x%08" PRIX32 ")",
1510
0
             szReaderA, SCardGetShareModeString(call->Common.dwShareMode),
1511
0
             call->Common.dwShareMode, SCardGetProtocolString(call->Common.dwPreferredProtocols),
1512
0
             call->Common.dwPreferredProtocols);
1513
0
  WLog_Print(log, g_LogLevel, "}");
1514
0
}
1515
1516
static void smartcard_trace_hcard_and_disposition_call(wLog* log,
1517
                                                       const HCardAndDisposition_Call* call,
1518
                                                       const char* name)
1519
0
{
1520
0
  WINPR_ASSERT(call);
1521
1522
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1523
0
    return;
1524
1525
0
  WLog_Print(log, g_LogLevel, "%s_Call {", name);
1526
0
  smartcard_log_context(log, &call->handles.hContext);
1527
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1528
1529
0
  WLog_Print(log, g_LogLevel, "dwDisposition: %s (0x%08" PRIX32 ")",
1530
0
             SCardGetDispositionString(call->dwDisposition), call->dwDisposition);
1531
0
  WLog_Print(log, g_LogLevel, "}");
1532
0
}
1533
1534
static void smartcard_trace_establish_context_call(wLog* log, const EstablishContext_Call* call)
1535
0
{
1536
0
  WINPR_ASSERT(call);
1537
1538
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1539
0
    return;
1540
1541
0
  WLog_Print(log, g_LogLevel, "EstablishContext_Call {");
1542
0
  WLog_Print(log, g_LogLevel, "dwScope: %s (0x%08" PRIX32 ")", SCardGetScopeString(call->dwScope),
1543
0
             call->dwScope);
1544
0
  WLog_Print(log, g_LogLevel, "}");
1545
0
}
1546
1547
static void smartcard_trace_establish_context_return(wLog* log, const EstablishContext_Return* ret)
1548
0
{
1549
0
  WINPR_ASSERT(ret);
1550
1551
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1552
0
    return;
1553
1554
0
  WLog_Print(log, g_LogLevel, "EstablishContext_Return {");
1555
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1556
0
             SCardGetErrorString(ret->ReturnCode),
1557
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1558
0
  smartcard_log_context(log, &ret->hContext);
1559
1560
0
  WLog_Print(log, g_LogLevel, "}");
1561
0
}
1562
1563
void smartcard_trace_long_return(const Long_Return* ret, const char* name)
1564
0
{
1565
0
  wLog* log = scard_log();
1566
0
  smartcard_trace_long_return_int(log, ret, name);
1567
0
}
1568
1569
void smartcard_trace_long_return_int(wLog* log, const Long_Return* ret, const char* name)
1570
0
{
1571
0
  WINPR_ASSERT(ret);
1572
1573
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1574
0
    return;
1575
1576
0
  WLog_Print(log, g_LogLevel, "%s_Return {", name);
1577
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1578
0
             SCardGetErrorString(ret->ReturnCode),
1579
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1580
0
  WLog_Print(log, g_LogLevel, "}");
1581
0
}
1582
1583
static void smartcard_trace_connect_return(wLog* log, const Connect_Return* ret)
1584
0
{
1585
0
  WINPR_ASSERT(ret);
1586
1587
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1588
0
    return;
1589
1590
0
  WLog_Print(log, g_LogLevel, "Connect_Return {");
1591
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1592
0
             SCardGetErrorString(ret->ReturnCode),
1593
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1594
0
  smartcard_log_context(log, &ret->hContext);
1595
0
  smartcard_log_redir_handle(log, &ret->hCard);
1596
1597
0
  WLog_Print(log, g_LogLevel, "  dwActiveProtocol: %s (0x%08" PRIX32 ")",
1598
0
             SCardGetProtocolString(ret->dwActiveProtocol), ret->dwActiveProtocol);
1599
0
  WLog_Print(log, g_LogLevel, "}");
1600
0
}
1601
1602
static void smartcard_trace_reconnect_call(wLog* log, const Reconnect_Call* call)
1603
0
{
1604
0
  WINPR_ASSERT(call);
1605
1606
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1607
0
    return;
1608
1609
0
  WLog_Print(log, g_LogLevel, "Reconnect_Call {");
1610
0
  smartcard_log_context(log, &call->handles.hContext);
1611
0
  smartcard_log_redir_handle(log, &call->handles.hCard);
1612
1613
0
  WLog_Print(log, g_LogLevel,
1614
0
             "dwShareMode: %s (0x%08" PRIX32 ") dwPreferredProtocols: %s (0x%08" PRIX32
1615
0
             ") dwInitialization: %s (0x%08" PRIX32 ")",
1616
0
             SCardGetShareModeString(call->dwShareMode), call->dwShareMode,
1617
0
             SCardGetProtocolString(call->dwPreferredProtocols), call->dwPreferredProtocols,
1618
0
             SCardGetDispositionString(call->dwInitialization), call->dwInitialization);
1619
0
  WLog_Print(log, g_LogLevel, "}");
1620
0
}
1621
1622
static void smartcard_trace_device_type_id_return(wLog* log, const GetDeviceTypeId_Return* ret)
1623
0
{
1624
0
  WINPR_ASSERT(ret);
1625
1626
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
1627
0
    return;
1628
1629
0
  WLog_Print(log, g_LogLevel, "GetDeviceTypeId_Return {");
1630
0
  WLog_Print(log, g_LogLevel, "  ReturnCode: %s (0x%08" PRIX32 ")",
1631
0
             SCardGetErrorString(ret->ReturnCode),
1632
0
             WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1633
0
  WLog_Print(log, g_LogLevel, "  dwDeviceId=%08" PRIx32, ret->dwDeviceId);
1634
1635
0
  WLog_Print(log, g_LogLevel, "}");
1636
0
}
1637
1638
static LONG smartcard_unpack_common_context_and_string_a(wLog* log, wStream* s,
1639
                                                         REDIR_SCARDCONTEXT* phContext,
1640
                                                         CHAR** pszReaderName)
1641
0
{
1642
0
  UINT32 index = 0;
1643
0
  UINT32 pbContextNdrPtr = 0;
1644
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, phContext, &index, &pbContextNdrPtr);
1645
0
  if (status != SCARD_S_SUCCESS)
1646
0
    return status;
1647
1648
0
  if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
1649
0
    return ERROR_INVALID_DATA;
1650
1651
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, phContext);
1652
0
  if (status != SCARD_S_SUCCESS)
1653
0
    return status;
1654
1655
0
  status = smartcard_ndr_read_a(log, s, pszReaderName, NDR_PTR_FULL);
1656
0
  if (status != SCARD_S_SUCCESS)
1657
0
    return status;
1658
1659
0
  smartcard_trace_context_and_string_call_a(log, __func__, phContext, *pszReaderName);
1660
0
  return SCARD_S_SUCCESS;
1661
0
}
1662
1663
static LONG smartcard_unpack_common_context_and_string_w(wLog* log, wStream* s,
1664
                                                         REDIR_SCARDCONTEXT* phContext,
1665
                                                         WCHAR** pszReaderName)
1666
0
{
1667
0
  UINT32 index = 0;
1668
0
  UINT32 pbContextNdrPtr = 0;
1669
1670
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, phContext, &index, &pbContextNdrPtr);
1671
0
  if (status != SCARD_S_SUCCESS)
1672
0
    return status;
1673
1674
0
  if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
1675
0
    return ERROR_INVALID_DATA;
1676
1677
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, phContext);
1678
0
  if (status != SCARD_S_SUCCESS)
1679
0
    return status;
1680
1681
0
  status = smartcard_ndr_read_w(log, s, pszReaderName, NDR_PTR_FULL);
1682
0
  if (status != SCARD_S_SUCCESS)
1683
0
    return status;
1684
1685
0
  smartcard_trace_context_and_string_call_w(log, __func__, phContext, *pszReaderName);
1686
0
  return SCARD_S_SUCCESS;
1687
0
}
1688
1689
LONG smartcard_unpack_common_type_header(wStream* s)
1690
0
{
1691
0
  wLog* log = scard_log();
1692
0
  UINT8 version = 0;
1693
0
  UINT32 filler = 0;
1694
0
  UINT8 endianness = 0;
1695
0
  UINT16 commonHeaderLength = 0;
1696
1697
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
1698
0
    return STATUS_BUFFER_TOO_SMALL;
1699
1700
  /* Process CommonTypeHeader */
1701
0
  Stream_Read_UINT8(s, version);             /* Version (1 byte) */
1702
0
  Stream_Read_UINT8(s, endianness);          /* Endianness (1 byte) */
1703
0
  Stream_Read_UINT16(s, commonHeaderLength); /* CommonHeaderLength (2 bytes) */
1704
0
  Stream_Read_UINT32(s, filler);             /* Filler (4 bytes), should be 0xCCCCCCCC */
1705
1706
0
  if (version != 1)
1707
0
  {
1708
0
    WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader Version %" PRIu8 "", version);
1709
0
    return STATUS_INVALID_PARAMETER;
1710
0
  }
1711
1712
0
  if (endianness != 0x10)
1713
0
  {
1714
0
    WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader Endianness %" PRIu8 "",
1715
0
               endianness);
1716
0
    return STATUS_INVALID_PARAMETER;
1717
0
  }
1718
1719
0
  if (commonHeaderLength != 8)
1720
0
  {
1721
0
    WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader CommonHeaderLength %" PRIu16 "",
1722
0
               commonHeaderLength);
1723
0
    return STATUS_INVALID_PARAMETER;
1724
0
  }
1725
1726
0
  if (filler != 0xCCCCCCCC)
1727
0
  {
1728
0
    WLog_Print(log, WLOG_WARN, "Unexpected CommonTypeHeader Filler 0x%08" PRIX32 "", filler);
1729
0
    return STATUS_INVALID_PARAMETER;
1730
0
  }
1731
1732
0
  return SCARD_S_SUCCESS;
1733
0
}
1734
1735
void smartcard_pack_common_type_header(wStream* s)
1736
0
{
1737
0
  Stream_Write_UINT8(s, 1);           /* Version (1 byte) */
1738
0
  Stream_Write_UINT8(s, 0x10);        /* Endianness (1 byte) */
1739
0
  Stream_Write_UINT16(s, 8);          /* CommonHeaderLength (2 bytes) */
1740
0
  Stream_Write_UINT32(s, 0xCCCCCCCC); /* Filler (4 bytes), should be 0xCCCCCCCC */
1741
0
}
1742
1743
LONG smartcard_unpack_private_type_header(wStream* s)
1744
0
{
1745
0
  wLog* log = scard_log();
1746
0
  UINT32 filler = 0;
1747
0
  UINT32 objectBufferLength = 0;
1748
1749
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
1750
0
    return STATUS_BUFFER_TOO_SMALL;
1751
1752
0
  Stream_Read_UINT32(s, objectBufferLength); /* ObjectBufferLength (4 bytes) */
1753
0
  Stream_Read_UINT32(s, filler);             /* Filler (4 bytes), should be 0x00000000 */
1754
1755
0
  if (filler != 0x00000000)
1756
0
  {
1757
0
    WLog_Print(log, WLOG_WARN, "Unexpected PrivateTypeHeader Filler 0x%08" PRIX32 "", filler);
1758
0
    return STATUS_INVALID_PARAMETER;
1759
0
  }
1760
1761
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, objectBufferLength))
1762
0
    return STATUS_INVALID_PARAMETER;
1763
1764
0
  return SCARD_S_SUCCESS;
1765
0
}
1766
1767
void smartcard_pack_private_type_header(wStream* s, UINT32 objectBufferLength)
1768
0
{
1769
0
  Stream_Write_UINT32(s, objectBufferLength); /* ObjectBufferLength (4 bytes) */
1770
0
  Stream_Write_UINT32(s, 0x00000000);         /* Filler (4 bytes), should be 0x00000000 */
1771
0
}
1772
1773
LONG smartcard_unpack_read_size_align(wStream* s, size_t size, UINT32 alignment)
1774
0
{
1775
0
  const size_t padsize = (size + alignment - 1) & ~(alignment - 1);
1776
0
  const size_t pad = padsize - size;
1777
1778
0
  if (pad > 0)
1779
0
  {
1780
0
    if (!Stream_SafeSeek(s, pad))
1781
0
      return -1;
1782
0
  }
1783
1784
0
  return (LONG)pad;
1785
0
}
1786
1787
LONG smartcard_pack_write_size_align(wStream* s, size_t size, UINT32 alignment)
1788
0
{
1789
0
  const size_t padsize = (size + alignment - 1) & ~(alignment - 1);
1790
0
  const size_t pad = padsize - size;
1791
1792
0
  if (pad)
1793
0
  {
1794
0
    if (!Stream_EnsureRemainingCapacity(s, pad))
1795
0
    {
1796
0
      wLog* log = scard_log();
1797
0
      WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
1798
0
      return SCARD_F_INTERNAL_ERROR;
1799
0
    }
1800
1801
0
    Stream_Zero(s, pad);
1802
0
  }
1803
1804
0
  return SCARD_S_SUCCESS;
1805
0
}
1806
1807
SCARDCONTEXT smartcard_scard_context_native_from_redir(const REDIR_SCARDCONTEXT* context)
1808
0
{
1809
0
  SCARDCONTEXT hContext = WINPR_C_ARRAY_INIT;
1810
1811
0
  WINPR_ASSERT(context);
1812
0
  if ((context->cbContext != sizeof(ULONG_PTR)) && (context->cbContext != 0))
1813
0
  {
1814
0
    wLog* log = scard_log();
1815
0
    WLog_Print(log, WLOG_WARN,
1816
0
               "REDIR_SCARDCONTEXT does not match native size: Actual: %" PRIu32
1817
0
               ", Expected: %" PRIuz "",
1818
0
               context->cbContext, sizeof(ULONG_PTR));
1819
0
    return 0;
1820
0
  }
1821
1822
0
  if (context->cbContext)
1823
0
    CopyMemory(&hContext, &(context->pbContext), context->cbContext);
1824
1825
0
  return hContext;
1826
0
}
1827
1828
void smartcard_scard_context_native_to_redir(REDIR_SCARDCONTEXT* context, SCARDCONTEXT hContext)
1829
0
{
1830
0
  WINPR_ASSERT(context);
1831
0
  ZeroMemory(context, sizeof(REDIR_SCARDCONTEXT));
1832
0
  context->cbContext = sizeof(ULONG_PTR);
1833
0
  CopyMemory(&(context->pbContext), &hContext, context->cbContext);
1834
0
}
1835
1836
SCARDHANDLE smartcard_scard_handle_native_from_redir(const REDIR_SCARDHANDLE* handle)
1837
0
{
1838
0
  SCARDHANDLE hCard = 0;
1839
1840
0
  WINPR_ASSERT(handle);
1841
0
  if (handle->cbHandle == 0)
1842
0
    return hCard;
1843
1844
0
  if (handle->cbHandle != sizeof(ULONG_PTR))
1845
0
  {
1846
0
    wLog* log = scard_log();
1847
0
    WLog_Print(log, WLOG_WARN,
1848
0
               "REDIR_SCARDHANDLE does not match native size: Actual: %" PRIu32
1849
0
               ", Expected: %" PRIuz "",
1850
0
               handle->cbHandle, sizeof(ULONG_PTR));
1851
0
    return 0;
1852
0
  }
1853
1854
0
  if (handle->cbHandle)
1855
0
    CopyMemory(&hCard, &(handle->pbHandle), handle->cbHandle);
1856
1857
0
  return hCard;
1858
0
}
1859
1860
void smartcard_scard_handle_native_to_redir(REDIR_SCARDHANDLE* handle, SCARDHANDLE hCard)
1861
0
{
1862
0
  WINPR_ASSERT(handle);
1863
0
  ZeroMemory(handle, sizeof(REDIR_SCARDHANDLE));
1864
0
  handle->cbHandle = sizeof(ULONG_PTR);
1865
0
  CopyMemory(&(handle->pbHandle), &hCard, handle->cbHandle);
1866
0
}
1867
1868
#define smartcard_context_supported(log, size) \
1869
0
  smartcard_context_supported_((log), (size), __FILE__, __func__, __LINE__)
1870
static LONG smartcard_context_supported_(wLog* log, uint32_t size, const char* file,
1871
                                         const char* fkt, size_t line)
1872
0
{
1873
0
  switch (size)
1874
0
  {
1875
0
    case 0:
1876
0
    case 4:
1877
0
    case 8:
1878
0
      return SCARD_S_SUCCESS;
1879
0
    default:
1880
0
    {
1881
0
      const uint32_t level = WLOG_WARN;
1882
0
      if (WLog_IsLevelActive(log, level))
1883
0
      {
1884
0
        WLog_PrintTextMessage(log, level, line, file, fkt,
1885
0
                              "REDIR_SCARDCONTEXT length is not 0, 4 or 8: %" PRIu32 "",
1886
0
                              size);
1887
0
      }
1888
0
      return STATUS_INVALID_PARAMETER;
1889
0
    }
1890
0
  }
1891
0
}
1892
1893
LONG smartcard_unpack_redir_scard_context_(wLog* log, wStream* s, REDIR_SCARDCONTEXT* context,
1894
                                           UINT32* index, UINT32* ppbContextNdrPtr,
1895
                                           const char* file, const char* function, size_t line)
1896
0
{
1897
0
  UINT32 pbContextNdrPtr = 0;
1898
1899
0
  WINPR_UNUSED(file);
1900
0
  WINPR_ASSERT(context);
1901
1902
0
  ZeroMemory(context, sizeof(REDIR_SCARDCONTEXT));
1903
1904
0
  if (!Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, 4, 1, "%s(%s:%" PRIuz ")", file,
1905
0
                                              function, line))
1906
0
    return STATUS_BUFFER_TOO_SMALL;
1907
1908
0
  const LONG status = smartcard_context_supported_(log, context->cbContext, file, function, line);
1909
0
  if (status != SCARD_S_SUCCESS)
1910
0
    return status;
1911
1912
0
  Stream_Read_UINT32(s, context->cbContext); /* cbContext (4 bytes) */
1913
1914
0
  if (!smartcard_ndr_pointer_read_(log, s, index, &pbContextNdrPtr, file, function, line))
1915
0
    return ERROR_INVALID_DATA;
1916
1917
0
  if (((context->cbContext == 0) && pbContextNdrPtr) ||
1918
0
      ((context->cbContext != 0) && !pbContextNdrPtr))
1919
0
  {
1920
0
    WLog_Print(log, WLOG_WARN,
1921
0
               "REDIR_SCARDCONTEXT cbContext (%" PRIu32 ") pbContextNdrPtr (%" PRIu32
1922
0
               ") inconsistency",
1923
0
               context->cbContext, pbContextNdrPtr);
1924
0
    return STATUS_INVALID_PARAMETER;
1925
0
  }
1926
1927
0
  *ppbContextNdrPtr = pbContextNdrPtr;
1928
0
  return SCARD_S_SUCCESS;
1929
0
}
1930
1931
LONG smartcard_pack_redir_scard_context(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1932
                                        const REDIR_SCARDCONTEXT* context, UINT32* index)
1933
0
{
1934
0
  const UINT32 pbContextNdrPtr = 0x00020000 + *index * 4;
1935
1936
0
  WINPR_ASSERT(context);
1937
0
  if (context->cbContext != 0)
1938
0
  {
1939
0
    Stream_Write_UINT32(s, context->cbContext); /* cbContext (4 bytes) */
1940
0
    Stream_Write_UINT32(s, pbContextNdrPtr);    /* pbContextNdrPtr (4 bytes) */
1941
0
    *index = *index + 1;
1942
0
  }
1943
0
  else
1944
0
    Stream_Zero(s, 8);
1945
1946
0
  return SCARD_S_SUCCESS;
1947
0
}
1948
1949
LONG smartcard_unpack_redir_scard_context_ref(wLog* log, wStream* s,
1950
                                              WINPR_ATTR_UNUSED UINT32 pbContextNdrPtr,
1951
                                              REDIR_SCARDCONTEXT* context)
1952
0
{
1953
0
  UINT32 length = 0;
1954
1955
0
  WINPR_ASSERT(context);
1956
1957
0
  if (context->cbContext == 0)
1958
0
    return SCARD_S_SUCCESS;
1959
1960
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
1961
0
    return STATUS_BUFFER_TOO_SMALL;
1962
1963
0
  Stream_Read_UINT32(s, length); /* Length (4 bytes) */
1964
1965
0
  if (length != context->cbContext)
1966
0
  {
1967
0
    WLog_Print(log, WLOG_WARN,
1968
0
               "REDIR_SCARDCONTEXT length (%" PRIu32 ") cbContext (%" PRIu32 ") mismatch",
1969
0
               length, context->cbContext);
1970
0
    return STATUS_INVALID_PARAMETER;
1971
0
  }
1972
1973
0
  const LONG status = smartcard_context_supported(log, context->cbContext);
1974
0
  if (status != SCARD_S_SUCCESS)
1975
0
    return status;
1976
1977
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, context->cbContext))
1978
0
    return STATUS_BUFFER_TOO_SMALL;
1979
1980
0
  if (context->cbContext)
1981
0
    Stream_Read(s, &(context->pbContext), context->cbContext);
1982
0
  else
1983
0
    ZeroMemory(&(context->pbContext), sizeof(context->pbContext));
1984
1985
0
  return SCARD_S_SUCCESS;
1986
0
}
1987
1988
LONG smartcard_pack_redir_scard_context_ref(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1989
                                            const REDIR_SCARDCONTEXT* context)
1990
0
{
1991
0
  WINPR_ASSERT(context);
1992
1993
0
  if (context->cbContext == 0)
1994
0
    return SCARD_S_SUCCESS;
1995
1996
0
  Stream_Write_UINT32(s, context->cbContext); /* Length (4 bytes) */
1997
0
  Stream_Write(s, &(context->pbContext), context->cbContext);
1998
1999
0
  return SCARD_S_SUCCESS;
2000
0
}
2001
2002
LONG smartcard_unpack_redir_scard_handle_(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle,
2003
                                          UINT32* index, const char* file, const char* function,
2004
                                          size_t line)
2005
0
{
2006
0
  UINT32 pbHandleNdrPtr = 0;
2007
2008
0
  WINPR_ASSERT(handle);
2009
0
  ZeroMemory(handle, sizeof(REDIR_SCARDHANDLE));
2010
2011
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2012
0
    return STATUS_BUFFER_TOO_SMALL;
2013
2014
0
  Stream_Read_UINT32(s, handle->cbHandle); /* Length (4 bytes) */
2015
2016
0
  if (!smartcard_ndr_pointer_read_(log, s, index, &pbHandleNdrPtr, file, function, line))
2017
0
    return ERROR_INVALID_DATA;
2018
2019
0
  if (((handle->cbHandle == 0) && pbHandleNdrPtr) ||
2020
0
      ((handle->cbHandle != 0) && !pbHandleNdrPtr))
2021
0
  {
2022
0
    WLog_Print(log, WLOG_WARN,
2023
0
               "REDIR_SCARDHANDLE cbHandle (%" PRIu32 ") pbHandleNdrPtr (%" PRIu32
2024
0
               ") inconsistency",
2025
0
               handle->cbHandle, pbHandleNdrPtr);
2026
0
    return STATUS_INVALID_PARAMETER;
2027
0
  }
2028
2029
0
  return SCARD_S_SUCCESS;
2030
0
}
2031
2032
LONG smartcard_pack_redir_scard_handle(WINPR_ATTR_UNUSED wLog* log, wStream* s,
2033
                                       const REDIR_SCARDHANDLE* handle, UINT32* index)
2034
0
{
2035
0
  const UINT32 pbContextNdrPtr = 0x00020000 + *index * 4;
2036
2037
0
  WINPR_ASSERT(handle);
2038
0
  if (handle->cbHandle != 0)
2039
0
  {
2040
0
    Stream_Write_UINT32(s, handle->cbHandle); /* cbContext (4 bytes) */
2041
0
    Stream_Write_UINT32(s, pbContextNdrPtr);  /* pbContextNdrPtr (4 bytes) */
2042
0
    *index = *index + 1;
2043
0
  }
2044
0
  else
2045
0
    Stream_Zero(s, 8);
2046
0
  return SCARD_S_SUCCESS;
2047
0
}
2048
2049
LONG smartcard_unpack_redir_scard_handle_ref(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle)
2050
0
{
2051
0
  UINT32 length = 0;
2052
2053
0
  WINPR_ASSERT(handle);
2054
2055
0
  if (handle->cbHandle == 0)
2056
0
    return SCARD_S_SUCCESS;
2057
2058
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2059
0
    return STATUS_BUFFER_TOO_SMALL;
2060
2061
0
  Stream_Read_UINT32(s, length); /* Length (4 bytes) */
2062
2063
0
  if (length != handle->cbHandle)
2064
0
  {
2065
0
    WLog_Print(log, WLOG_WARN,
2066
0
               "REDIR_SCARDHANDLE length (%" PRIu32 ") cbHandle (%" PRIu32 ") mismatch", length,
2067
0
               handle->cbHandle);
2068
0
    return STATUS_INVALID_PARAMETER;
2069
0
  }
2070
2071
0
  if ((handle->cbHandle != 4) && (handle->cbHandle != 8))
2072
0
  {
2073
0
    WLog_Print(log, WLOG_WARN, "REDIR_SCARDHANDLE length is not 4 or 8: %" PRIu32 "",
2074
0
               handle->cbHandle);
2075
0
    return STATUS_INVALID_PARAMETER;
2076
0
  }
2077
2078
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, handle->cbHandle))
2079
0
    return STATUS_BUFFER_TOO_SMALL;
2080
2081
0
  if (handle->cbHandle)
2082
0
    Stream_Read(s, &(handle->pbHandle), handle->cbHandle);
2083
2084
0
  return SCARD_S_SUCCESS;
2085
0
}
2086
2087
LONG smartcard_pack_redir_scard_handle_ref(WINPR_ATTR_UNUSED wLog* log, wStream* s,
2088
                                           const REDIR_SCARDHANDLE* handle)
2089
0
{
2090
0
  WINPR_ASSERT(handle);
2091
2092
0
  if (handle->cbHandle == 0)
2093
0
    return SCARD_S_SUCCESS;
2094
2095
0
  Stream_Write_UINT32(s, handle->cbHandle); /* Length (4 bytes) */
2096
0
  Stream_Write(s, &(handle->pbHandle), handle->cbHandle);
2097
2098
0
  return SCARD_S_SUCCESS;
2099
0
}
2100
2101
LONG smartcard_unpack_establish_context_call(wStream* s, EstablishContext_Call* call)
2102
0
{
2103
0
  WINPR_ASSERT(call);
2104
0
  wLog* log = scard_log();
2105
2106
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2107
0
    return STATUS_BUFFER_TOO_SMALL;
2108
2109
0
  Stream_Read_UINT32(s, call->dwScope); /* dwScope (4 bytes) */
2110
0
  smartcard_trace_establish_context_call(log, call);
2111
0
  return SCARD_S_SUCCESS;
2112
0
}
2113
2114
LONG smartcard_pack_establish_context_call(wStream* s, const EstablishContext_Call* call)
2115
0
{
2116
0
  WINPR_ASSERT(call);
2117
0
  wLog* log = scard_log();
2118
2119
0
  smartcard_trace_establish_context_call(log, call);
2120
2121
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
2122
0
    return SCARD_E_NO_MEMORY;
2123
2124
0
  Stream_Write_UINT32(s, call->dwScope);
2125
2126
0
  return SCARD_S_SUCCESS;
2127
0
}
2128
2129
LONG smartcard_pack_establish_context_return(wStream* s, const EstablishContext_Return* ret)
2130
0
{
2131
0
  WINPR_ASSERT(ret);
2132
0
  wLog* log = scard_log();
2133
0
  LONG status = 0;
2134
0
  UINT32 index = 0;
2135
2136
0
  smartcard_trace_establish_context_return(log, ret);
2137
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
2138
0
    return ret->ReturnCode;
2139
2140
0
  status = smartcard_pack_redir_scard_context(log, s, &(ret->hContext), &index);
2141
0
  if (status != SCARD_S_SUCCESS)
2142
0
    return status;
2143
2144
0
  return smartcard_pack_redir_scard_context_ref(log, s, &(ret->hContext));
2145
0
}
2146
2147
LONG smartcard_unpack_establish_context_return(wStream* s, EstablishContext_Return* ret)
2148
0
{
2149
0
  WINPR_ASSERT(ret);
2150
0
  wLog* log = scard_log();
2151
0
  UINT32 index = 0;
2152
0
  UINT32 pbContextNdrPtr = 0;
2153
2154
0
  LONG status =
2155
0
      smartcard_unpack_redir_scard_context(log, s, &(ret->hContext), &index, &pbContextNdrPtr);
2156
0
  if (status != SCARD_S_SUCCESS)
2157
0
    return status;
2158
2159
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &(ret->hContext));
2160
0
  if (status != SCARD_S_SUCCESS)
2161
0
    return status;
2162
2163
0
  smartcard_trace_establish_context_return(log, ret);
2164
0
  return SCARD_S_SUCCESS;
2165
0
}
2166
2167
LONG smartcard_unpack_context_call(wStream* s, Context_Call* call, const char* name)
2168
0
{
2169
0
  UINT32 index = 0;
2170
0
  UINT32 pbContextNdrPtr = 0;
2171
0
  wLog* log = scard_log();
2172
2173
0
  WINPR_ASSERT(call);
2174
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2175
0
                                                     &pbContextNdrPtr);
2176
0
  if (status != SCARD_S_SUCCESS)
2177
0
    return status;
2178
2179
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2180
0
                                                    &(call->handles.hContext));
2181
0
  if (status != SCARD_S_SUCCESS)
2182
0
    WLog_Print(log, WLOG_ERROR,
2183
0
               "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2184
0
               status);
2185
2186
0
  smartcard_trace_context_call(log, call, name);
2187
0
  return status;
2188
0
}
2189
2190
LONG smartcard_unpack_list_reader_groups_call(wStream* s, ListReaderGroups_Call* call, BOOL unicode)
2191
0
{
2192
0
  UINT32 index = 0;
2193
0
  UINT32 pbContextNdrPtr = 0;
2194
0
  wLog* log = scard_log();
2195
2196
0
  WINPR_ASSERT(call);
2197
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2198
0
                                                     &pbContextNdrPtr);
2199
2200
0
  if (status != SCARD_S_SUCCESS)
2201
0
    return status;
2202
2203
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2204
0
    return STATUS_BUFFER_TOO_SMALL;
2205
2206
0
  Stream_Read_INT32(s, call->fmszGroupsIsNULL); /* fmszGroupsIsNULL (4 bytes) */
2207
0
  Stream_Read_UINT32(s, call->cchGroups);       /* cchGroups (4 bytes) */
2208
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2209
0
                                                    &(call->handles.hContext));
2210
2211
0
  if (status != SCARD_S_SUCCESS)
2212
0
    return status;
2213
2214
0
  smartcard_trace_list_reader_groups_call(log, call, unicode);
2215
0
  return SCARD_S_SUCCESS;
2216
0
}
2217
2218
LONG smartcard_pack_list_reader_groups_call(wStream* s, const ListReaderGroups_Call* call,
2219
                                            BOOL unicode)
2220
0
{
2221
0
  WINPR_ASSERT(call);
2222
0
  wLog* log = scard_log();
2223
0
  UINT32 index = 0;
2224
2225
0
  smartcard_trace_list_reader_groups_call(log, call, unicode);
2226
2227
0
  LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
2228
0
  if (status != SCARD_S_SUCCESS)
2229
0
    return status;
2230
2231
0
  if (!Stream_EnsureRemainingCapacity(s, 8))
2232
0
    return SCARD_E_NO_MEMORY;
2233
2234
0
  Stream_Write_INT32(s, call->fmszGroupsIsNULL);
2235
0
  Stream_Write_UINT32(s, call->cchGroups);
2236
2237
0
  return smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
2238
0
}
2239
2240
LONG smartcard_pack_list_reader_groups_return(wStream* s, const ListReaderGroups_Return* ret,
2241
                                              BOOL unicode)
2242
0
{
2243
0
  WINPR_ASSERT(ret);
2244
0
  wLog* log = scard_log();
2245
0
  LONG status = 0;
2246
0
  UINT32 cBytes = ret->cBytes;
2247
0
  UINT32 index = 0;
2248
2249
0
  smartcard_trace_list_reader_groups_return(log, ret, unicode);
2250
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
2251
0
    cBytes = 0;
2252
0
  if (cBytes == SCARD_AUTOALLOCATE)
2253
0
    cBytes = 0;
2254
2255
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
2256
0
    return SCARD_E_NO_MEMORY;
2257
2258
0
  Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
2259
0
  if (!smartcard_ndr_pointer_write(s, &index, cBytes))
2260
0
    return SCARD_E_NO_MEMORY;
2261
2262
0
  status = smartcard_ndr_write(s, ret->msz, cBytes, 1, NDR_PTR_SIMPLE);
2263
0
  if (status != SCARD_S_SUCCESS)
2264
0
    return status;
2265
0
  return ret->ReturnCode;
2266
0
}
2267
2268
LONG smartcard_unpack_list_reader_groups_return(wStream* s, ListReaderGroups_Return* ret,
2269
                                                BOOL unicode)
2270
0
{
2271
0
  WINPR_ASSERT(ret);
2272
0
  wLog* log = scard_log();
2273
0
  UINT32 index = 0;
2274
0
  UINT32 mszNdrPtr = 0;
2275
2276
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2277
0
    return STATUS_BUFFER_TOO_SMALL;
2278
2279
0
  const UINT32 cBytes = Stream_Get_UINT32(s);
2280
2281
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
2282
0
    return ERROR_INVALID_DATA;
2283
2284
0
  if (mszNdrPtr)
2285
0
  {
2286
0
    LONG status = smartcard_ndr_read(log, s, &ret->msz, cBytes, 1, NDR_PTR_SIMPLE);
2287
0
    if (status != SCARD_S_SUCCESS)
2288
0
      return status;
2289
0
    ret->cBytes = cBytes;
2290
0
  }
2291
2292
0
  smartcard_trace_list_reader_groups_return(log, ret, unicode);
2293
0
  return SCARD_S_SUCCESS;
2294
0
}
2295
2296
LONG smartcard_unpack_list_readers_call(wStream* s, ListReaders_Call* call, BOOL unicode)
2297
0
{
2298
0
  UINT32 index = 0;
2299
0
  UINT32 mszGroupsNdrPtr = 0;
2300
0
  UINT32 pbContextNdrPtr = 0;
2301
0
  wLog* log = scard_log();
2302
2303
0
  WINPR_ASSERT(call);
2304
0
  call->mszGroups = nullptr;
2305
2306
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2307
0
                                                     &pbContextNdrPtr);
2308
0
  if (status != SCARD_S_SUCCESS)
2309
0
    return status;
2310
2311
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2312
0
    return STATUS_BUFFER_TOO_SMALL;
2313
2314
0
  const UINT32 cBytes = Stream_Get_UINT32(s);
2315
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &mszGroupsNdrPtr))
2316
0
    return ERROR_INVALID_DATA;
2317
2318
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2319
0
    return STATUS_BUFFER_TOO_SMALL;
2320
0
  Stream_Read_INT32(s, call->fmszReadersIsNULL); /* fmszReadersIsNULL (4 bytes) */
2321
0
  Stream_Read_UINT32(s, call->cchReaders);       /* cchReaders (4 bytes) */
2322
2323
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2324
0
                                                    &(call->handles.hContext));
2325
0
  if (status != SCARD_S_SUCCESS)
2326
0
    return status;
2327
2328
0
  if (mszGroupsNdrPtr)
2329
0
  {
2330
0
    status = smartcard_ndr_read(log, s, &call->mszGroups, cBytes, 1, NDR_PTR_SIMPLE);
2331
0
    if (status != SCARD_S_SUCCESS)
2332
0
      return status;
2333
0
    call->cBytes = cBytes;
2334
0
  }
2335
2336
0
  smartcard_trace_list_readers_call(log, call, unicode);
2337
0
  return SCARD_S_SUCCESS;
2338
0
}
2339
2340
LONG smartcard_pack_list_readers_return(wStream* s, const ListReaders_Return* ret, BOOL unicode)
2341
0
{
2342
0
  WINPR_ASSERT(ret);
2343
0
  wLog* log = scard_log();
2344
0
  LONG status = 0;
2345
0
  UINT32 index = 0;
2346
0
  UINT32 size = ret->cBytes;
2347
2348
0
  smartcard_trace_list_readers_return(log, ret, unicode);
2349
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
2350
0
    size = 0;
2351
2352
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
2353
0
  {
2354
0
    WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
2355
0
    return SCARD_F_INTERNAL_ERROR;
2356
0
  }
2357
2358
0
  Stream_Write_UINT32(s, size); /* cBytes (4 bytes) */
2359
0
  if (!smartcard_ndr_pointer_write(s, &index, size))
2360
0
    return SCARD_E_NO_MEMORY;
2361
2362
0
  status = smartcard_ndr_write(s, ret->msz, size, 1, NDR_PTR_SIMPLE);
2363
0
  if (status != SCARD_S_SUCCESS)
2364
0
    return status;
2365
0
  return ret->ReturnCode;
2366
0
}
2367
2368
static LONG smartcard_unpack_connect_common(wLog* log, wStream* s, Connect_Common_Call* common,
2369
                                            UINT32* index, UINT32* ppbContextNdrPtr)
2370
0
{
2371
0
  WINPR_ASSERT(common);
2372
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(common->handles.hContext), index,
2373
0
                                                     ppbContextNdrPtr);
2374
0
  if (status != SCARD_S_SUCCESS)
2375
0
    return status;
2376
2377
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2378
0
    return STATUS_BUFFER_TOO_SMALL;
2379
2380
0
  Stream_Read_UINT32(s, common->dwShareMode);          /* dwShareMode (4 bytes) */
2381
0
  Stream_Read_UINT32(s, common->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
2382
0
  return SCARD_S_SUCCESS;
2383
0
}
2384
2385
LONG smartcard_unpack_connect_a_call(wStream* s, ConnectA_Call* call)
2386
0
{
2387
0
  LONG status = 0;
2388
0
  UINT32 index = 0;
2389
0
  UINT32 pbContextNdrPtr = 0;
2390
2391
0
  WINPR_ASSERT(call);
2392
0
  wLog* log = scard_log();
2393
2394
0
  call->szReader = nullptr;
2395
2396
0
  if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
2397
0
    return ERROR_INVALID_DATA;
2398
2399
0
  status = smartcard_unpack_connect_common(log, s, &(call->Common), &index, &pbContextNdrPtr);
2400
0
  if (status != SCARD_S_SUCCESS)
2401
0
  {
2402
0
    WLog_Print(log, WLOG_ERROR, "smartcard_unpack_connect_common failed with error %" PRId32 "",
2403
0
               status);
2404
0
    return status;
2405
0
  }
2406
2407
0
  status = smartcard_ndr_read_a(log, s, &call->szReader, NDR_PTR_FULL);
2408
0
  if (status != SCARD_S_SUCCESS)
2409
0
    return status;
2410
2411
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2412
0
                                                    &(call->Common.handles.hContext));
2413
0
  if (status != SCARD_S_SUCCESS)
2414
0
    WLog_Print(log, WLOG_ERROR,
2415
0
               "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2416
0
               status);
2417
2418
0
  smartcard_trace_connect_a_call(log, call);
2419
0
  return status;
2420
0
}
2421
2422
LONG smartcard_unpack_connect_w_call(wStream* s, ConnectW_Call* call)
2423
0
{
2424
0
  LONG status = 0;
2425
0
  UINT32 index = 0;
2426
0
  UINT32 pbContextNdrPtr = 0;
2427
2428
0
  WINPR_ASSERT(call);
2429
0
  wLog* log = scard_log();
2430
0
  call->szReader = nullptr;
2431
2432
0
  if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
2433
0
    return ERROR_INVALID_DATA;
2434
2435
0
  status = smartcard_unpack_connect_common(log, s, &(call->Common), &index, &pbContextNdrPtr);
2436
0
  if (status != SCARD_S_SUCCESS)
2437
0
  {
2438
0
    WLog_Print(log, WLOG_ERROR, "smartcard_unpack_connect_common failed with error %" PRId32 "",
2439
0
               status);
2440
0
    return status;
2441
0
  }
2442
2443
0
  status = smartcard_ndr_read_w(log, s, &call->szReader, NDR_PTR_FULL);
2444
0
  if (status != SCARD_S_SUCCESS)
2445
0
    return status;
2446
2447
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2448
0
                                                    &(call->Common.handles.hContext));
2449
0
  if (status != SCARD_S_SUCCESS)
2450
0
    WLog_Print(log, WLOG_ERROR,
2451
0
               "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2452
0
               status);
2453
2454
0
  smartcard_trace_connect_w_call(log, call);
2455
0
  return status;
2456
0
}
2457
2458
LONG smartcard_pack_connect_return(wStream* s, const Connect_Return* ret)
2459
0
{
2460
0
  LONG status = 0;
2461
0
  UINT32 index = 0;
2462
2463
0
  WINPR_ASSERT(ret);
2464
0
  wLog* log = scard_log();
2465
0
  smartcard_trace_connect_return(log, ret);
2466
2467
0
  status = smartcard_pack_redir_scard_context(log, s, &ret->hContext, &index);
2468
0
  if (status != SCARD_S_SUCCESS)
2469
0
    return status;
2470
2471
0
  status = smartcard_pack_redir_scard_handle(log, s, &ret->hCard, &index);
2472
0
  if (status != SCARD_S_SUCCESS)
2473
0
    return status;
2474
2475
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
2476
0
    return SCARD_E_NO_MEMORY;
2477
2478
0
  Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
2479
0
  status = smartcard_pack_redir_scard_context_ref(log, s, &ret->hContext);
2480
0
  if (status != SCARD_S_SUCCESS)
2481
0
    return status;
2482
0
  return smartcard_pack_redir_scard_handle_ref(log, s, &(ret->hCard));
2483
0
}
2484
2485
LONG smartcard_unpack_reconnect_call(wStream* s, Reconnect_Call* call)
2486
0
{
2487
0
  UINT32 index = 0;
2488
0
  UINT32 pbContextNdrPtr = 0;
2489
2490
0
  WINPR_ASSERT(call);
2491
0
  wLog* log = scard_log();
2492
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2493
0
                                                     &pbContextNdrPtr);
2494
0
  if (status != SCARD_S_SUCCESS)
2495
0
    return status;
2496
2497
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2498
0
  if (status != SCARD_S_SUCCESS)
2499
0
    return status;
2500
2501
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
2502
0
    return STATUS_BUFFER_TOO_SMALL;
2503
2504
0
  Stream_Read_UINT32(s, call->dwShareMode);          /* dwShareMode (4 bytes) */
2505
0
  Stream_Read_UINT32(s, call->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
2506
0
  Stream_Read_UINT32(s, call->dwInitialization);     /* dwInitialization (4 bytes) */
2507
2508
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2509
0
                                                    &(call->handles.hContext));
2510
0
  if (status != SCARD_S_SUCCESS)
2511
0
  {
2512
0
    WLog_Print(log, WLOG_ERROR,
2513
0
               "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2514
0
               status);
2515
0
    return status;
2516
0
  }
2517
2518
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2519
0
  if (status != SCARD_S_SUCCESS)
2520
0
    WLog_Print(log, WLOG_ERROR,
2521
0
               "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status);
2522
2523
0
  smartcard_trace_reconnect_call(log, call);
2524
0
  return status;
2525
0
}
2526
2527
LONG smartcard_pack_reconnect_call(wStream* s, const Reconnect_Call* call)
2528
0
{
2529
0
  WINPR_ASSERT(call);
2530
0
  wLog* log = scard_log();
2531
0
  UINT32 index = 0;
2532
2533
0
  smartcard_trace_reconnect_call(log, call);
2534
2535
0
  LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
2536
0
  if (status != SCARD_S_SUCCESS)
2537
0
    return status;
2538
2539
0
  status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
2540
0
  if (status != SCARD_S_SUCCESS)
2541
0
    return status;
2542
2543
0
  if (!Stream_EnsureRemainingCapacity(s, 12))
2544
0
    return SCARD_E_NO_MEMORY;
2545
2546
0
  Stream_Write_UINT32(s, call->dwShareMode);
2547
0
  Stream_Write_UINT32(s, call->dwPreferredProtocols);
2548
0
  Stream_Write_UINT32(s, call->dwInitialization);
2549
2550
0
  status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
2551
0
  if (status != SCARD_S_SUCCESS)
2552
0
    return status;
2553
2554
0
  return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
2555
0
}
2556
2557
LONG smartcard_pack_reconnect_return(wStream* s, const Reconnect_Return* ret)
2558
0
{
2559
0
  WINPR_ASSERT(ret);
2560
0
  wLog* log = scard_log();
2561
0
  smartcard_trace_reconnect_return(log, ret);
2562
2563
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
2564
0
    return SCARD_E_NO_MEMORY;
2565
0
  Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
2566
0
  return ret->ReturnCode;
2567
0
}
2568
2569
LONG smartcard_unpack_reconnect_return(wStream* s, Reconnect_Return* ret)
2570
0
{
2571
0
  WINPR_ASSERT(ret);
2572
0
  wLog* log = scard_log();
2573
2574
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2575
0
    return STATUS_BUFFER_TOO_SMALL;
2576
2577
0
  Stream_Read_UINT32(s, ret->dwActiveProtocol);
2578
2579
0
  smartcard_trace_reconnect_return(log, ret);
2580
0
  return SCARD_S_SUCCESS;
2581
0
}
2582
2583
LONG smartcard_unpack_hcard_and_disposition_call(wStream* s, HCardAndDisposition_Call* call,
2584
                                                 const char* name)
2585
0
{
2586
0
  UINT32 index = 0;
2587
0
  UINT32 pbContextNdrPtr = 0;
2588
2589
0
  WINPR_ASSERT(call);
2590
0
  wLog* log = scard_log();
2591
2592
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2593
0
                                                     &pbContextNdrPtr);
2594
0
  if (status != SCARD_S_SUCCESS)
2595
0
    return status;
2596
2597
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2598
0
  if (status != SCARD_S_SUCCESS)
2599
0
    return status;
2600
2601
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2602
0
    return STATUS_BUFFER_TOO_SMALL;
2603
2604
0
  Stream_Read_UINT32(s, call->dwDisposition); /* dwDisposition (4 bytes) */
2605
2606
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2607
0
                                                    &(call->handles.hContext));
2608
0
  if (status != SCARD_S_SUCCESS)
2609
0
    return status;
2610
2611
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2612
0
  if (status != SCARD_S_SUCCESS)
2613
0
    return status;
2614
2615
0
  smartcard_trace_hcard_and_disposition_call(log, call, name);
2616
0
  return status;
2617
0
}
2618
2619
static void smartcard_trace_get_status_change_a_call(wLog* log, const GetStatusChangeA_Call* call)
2620
0
{
2621
0
  WINPR_ASSERT(call);
2622
2623
0
  if (!WLog_IsLevelActive(log, g_LogLevel))
2624
0
    return;
2625
2626
0
  WLog_Print(log, g_LogLevel, "GetStatusChangeA_Call {");
2627
0
  smartcard_log_context(log, &call->handles.hContext);
2628
2629
0
  WLog_Print(log, g_LogLevel, "dwTimeOut: 0x%08" PRIX32 " cReaders: %" PRIu32 "", call->dwTimeOut,
2630
0
             call->cReaders);
2631
2632
0
  dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
2633
2634
0
  WLog_Print(log, g_LogLevel, "}");
2635
0
}
2636
2637
static LONG smartcard_unpack_reader_state_a(wLog* log, wStream* s, LPSCARD_READERSTATEA* ppcReaders,
2638
                                            UINT32 cReaders, UINT32* ptrIndex)
2639
0
{
2640
0
  LONG status = SCARD_E_NO_MEMORY;
2641
2642
0
  WINPR_ASSERT(ppcReaders || (cReaders == 0));
2643
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2644
0
    return status;
2645
2646
0
  const UINT32 len = Stream_Get_UINT32(s);
2647
0
  if (len != cReaders)
2648
0
  {
2649
0
    WLog_Print(log, WLOG_ERROR, "Count mismatch when reading LPSCARD_READERSTATEA");
2650
0
    return status;
2651
0
  }
2652
2653
0
  LPSCARD_READERSTATEA rgReaderStates =
2654
0
      (LPSCARD_READERSTATEA)calloc(cReaders, sizeof(SCARD_READERSTATEA));
2655
0
  BOOL* states = calloc(cReaders, sizeof(BOOL));
2656
0
  if (!rgReaderStates || !states)
2657
0
    goto fail;
2658
0
  status = ERROR_INVALID_DATA;
2659
2660
0
  for (UINT32 index = 0; index < cReaders; index++)
2661
0
  {
2662
0
    UINT32 ptr = UINT32_MAX;
2663
0
    LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2664
2665
0
    if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 52))
2666
0
      goto fail;
2667
2668
0
    if (!smartcard_ndr_pointer_read(log, s, ptrIndex, &ptr))
2669
0
    {
2670
0
      if (ptr != 0)
2671
0
        goto fail;
2672
0
    }
2673
    /* Ignore nullptr length strings */
2674
0
    states[index] = ptr != 0;
2675
0
    Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2676
0
    Stream_Read_UINT32(s, readerState->dwEventState);   /* dwEventState (4 bytes) */
2677
0
    Stream_Read_UINT32(s, readerState->cbAtr);          /* cbAtr (4 bytes) */
2678
0
    if (readerState->cbAtr > ARRAYSIZE(readerState->rgbAtr))
2679
0
    {
2680
0
      WLog_Print(log, WLOG_ERROR,
2681
0
                 "SCARD_READERSTATEA[%" PRIu32 "]::cbAtr %" PRIu32 " exceeds %" PRIuz, index,
2682
0
                 readerState->cbAtr, (size_t)ARRAYSIZE(readerState->rgbAtr));
2683
0
      goto fail;
2684
0
    }
2685
0
    Stream_Read(s, readerState->rgbAtr, 36);            /* rgbAtr [0..36] (36 bytes) */
2686
0
  }
2687
2688
0
  for (UINT32 index = 0; index < cReaders; index++)
2689
0
  {
2690
0
    LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2691
2692
    /* Ignore empty strings */
2693
0
    if (!states[index])
2694
0
      continue;
2695
0
    status = smartcard_ndr_read_a(log, s, &readerState->szReader, NDR_PTR_FULL);
2696
0
    if (status != SCARD_S_SUCCESS)
2697
0
      goto fail;
2698
0
  }
2699
2700
0
  *ppcReaders = rgReaderStates;
2701
0
  free(states);
2702
0
  return SCARD_S_SUCCESS;
2703
0
fail:
2704
0
  if (rgReaderStates)
2705
0
  {
2706
0
    for (UINT32 index = 0; index < cReaders; index++)
2707
0
    {
2708
0
      LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2709
0
      free(readerState->szReader);
2710
0
    }
2711
0
  }
2712
0
  free(rgReaderStates);
2713
0
  free(states);
2714
0
  return status;
2715
0
}
2716
2717
static LONG smartcard_unpack_reader_state_w(wLog* log, wStream* s, LPSCARD_READERSTATEW* ppcReaders,
2718
                                            UINT32 cReaders, UINT32* ptrIndex)
2719
0
{
2720
0
  LONG status = SCARD_E_NO_MEMORY;
2721
2722
0
  WINPR_ASSERT(ppcReaders || (cReaders == 0));
2723
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2724
0
    return status;
2725
2726
0
  const UINT32 len = Stream_Get_UINT32(s);
2727
0
  if (len != cReaders)
2728
0
  {
2729
0
    WLog_Print(log, WLOG_ERROR, "Count mismatch when reading LPSCARD_READERSTATEW");
2730
0
    return status;
2731
0
  }
2732
2733
0
  LPSCARD_READERSTATEW rgReaderStates =
2734
0
      (LPSCARD_READERSTATEW)calloc(cReaders, sizeof(SCARD_READERSTATEW));
2735
0
  BOOL* states = calloc(cReaders, sizeof(BOOL));
2736
2737
0
  if (!rgReaderStates || !states)
2738
0
    goto fail;
2739
2740
0
  status = ERROR_INVALID_DATA;
2741
0
  for (UINT32 index = 0; index < cReaders; index++)
2742
0
  {
2743
0
    UINT32 ptr = UINT32_MAX;
2744
0
    LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2745
2746
0
    if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 52))
2747
0
      goto fail;
2748
2749
0
    if (!smartcard_ndr_pointer_read(log, s, ptrIndex, &ptr))
2750
0
    {
2751
0
      if (ptr != 0)
2752
0
        goto fail;
2753
0
    }
2754
    /* Ignore nullptr length strings */
2755
0
    states[index] = ptr != 0;
2756
0
    Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2757
0
    Stream_Read_UINT32(s, readerState->dwEventState);   /* dwEventState (4 bytes) */
2758
0
    Stream_Read_UINT32(s, readerState->cbAtr);          /* cbAtr (4 bytes) */
2759
0
    if (readerState->cbAtr > ARRAYSIZE(readerState->rgbAtr))
2760
0
    {
2761
0
      WLog_Print(log, WLOG_ERROR,
2762
0
                 "SCARD_READERSTATEW[%" PRIu32 "]::cbAtr %" PRIu32 " exceeds %" PRIuz, index,
2763
0
                 readerState->cbAtr, (size_t)ARRAYSIZE(readerState->rgbAtr));
2764
0
      goto fail;
2765
0
    }
2766
0
    Stream_Read(s, readerState->rgbAtr, 36);            /* rgbAtr [0..36] (36 bytes) */
2767
0
  }
2768
2769
0
  for (UINT32 index = 0; index < cReaders; index++)
2770
0
  {
2771
0
    LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2772
2773
    /* Skip nullptr pointers */
2774
0
    if (!states[index])
2775
0
      continue;
2776
2777
0
    status = smartcard_ndr_read_w(log, s, &readerState->szReader, NDR_PTR_FULL);
2778
0
    if (status != SCARD_S_SUCCESS)
2779
0
      goto fail;
2780
0
  }
2781
2782
0
  *ppcReaders = rgReaderStates;
2783
0
  free(states);
2784
0
  return SCARD_S_SUCCESS;
2785
0
fail:
2786
0
  if (rgReaderStates)
2787
0
  {
2788
0
    for (UINT32 index = 0; index < cReaders; index++)
2789
0
    {
2790
0
      LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2791
0
      free(readerState->szReader);
2792
0
    }
2793
0
  }
2794
0
  free(rgReaderStates);
2795
0
  free(states);
2796
0
  return status;
2797
0
}
2798
2799
/******************************************************************************/
2800
/************************************* End Trace Functions ********************/
2801
/******************************************************************************/
2802
2803
LONG smartcard_unpack_get_status_change_a_call(wStream* s, GetStatusChangeA_Call* call)
2804
0
{
2805
0
  UINT32 ndrPtr = 0;
2806
0
  UINT32 index = 0;
2807
0
  UINT32 pbContextNdrPtr = 0;
2808
2809
0
  WINPR_ASSERT(call);
2810
0
  wLog* log = scard_log();
2811
2812
0
  call->rgReaderStates = nullptr;
2813
2814
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2815
0
                                                     &pbContextNdrPtr);
2816
0
  if (status != SCARD_S_SUCCESS)
2817
0
    return status;
2818
2819
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2820
0
    return STATUS_BUFFER_TOO_SMALL;
2821
2822
0
  Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2823
0
  const UINT32 cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
2824
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
2825
0
    return ERROR_INVALID_DATA;
2826
2827
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2828
0
                                                    &(call->handles.hContext));
2829
0
  if (status != SCARD_S_SUCCESS)
2830
0
    return status;
2831
2832
0
  if (ndrPtr)
2833
0
  {
2834
0
    status = smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, cReaders, &index);
2835
0
    if (status != SCARD_S_SUCCESS)
2836
0
      return status;
2837
0
    call->cReaders = cReaders;
2838
0
  }
2839
0
  else
2840
0
  {
2841
0
    WLog_Print(log, WLOG_WARN, "ndrPtr=0x%08" PRIx32 ", can not read rgReaderStates", ndrPtr);
2842
0
    return SCARD_E_UNEXPECTED;
2843
0
  }
2844
2845
0
  smartcard_trace_get_status_change_a_call(log, call);
2846
0
  return SCARD_S_SUCCESS;
2847
0
}
2848
2849
LONG smartcard_unpack_get_status_change_w_call(wStream* s, GetStatusChangeW_Call* call)
2850
0
{
2851
0
  UINT32 ndrPtr = 0;
2852
0
  UINT32 index = 0;
2853
0
  UINT32 pbContextNdrPtr = 0;
2854
2855
0
  WINPR_ASSERT(call);
2856
0
  wLog* log = scard_log();
2857
0
  call->rgReaderStates = nullptr;
2858
2859
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2860
0
                                                     &pbContextNdrPtr);
2861
0
  if (status != SCARD_S_SUCCESS)
2862
0
    return status;
2863
2864
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2865
0
    return STATUS_BUFFER_TOO_SMALL;
2866
2867
0
  Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2868
0
  const UINT32 cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
2869
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
2870
0
    return ERROR_INVALID_DATA;
2871
2872
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2873
0
                                                    &(call->handles.hContext));
2874
0
  if (status != SCARD_S_SUCCESS)
2875
0
    return status;
2876
2877
0
  if (ndrPtr)
2878
0
  {
2879
0
    status = smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, cReaders, &index);
2880
0
    if (status != SCARD_S_SUCCESS)
2881
0
      return status;
2882
0
    call->cReaders = cReaders;
2883
0
  }
2884
0
  else
2885
0
  {
2886
0
    WLog_Print(log, WLOG_WARN, "ndrPtr=0x%08" PRIx32 ", can not read rgReaderStates", ndrPtr);
2887
0
    return SCARD_E_UNEXPECTED;
2888
0
  }
2889
2890
0
  smartcard_trace_get_status_change_w_call(log, call);
2891
0
  return SCARD_S_SUCCESS;
2892
0
}
2893
2894
LONG smartcard_pack_get_status_change_return(wStream* s, const GetStatusChange_Return* ret,
2895
                                             BOOL unicode)
2896
0
{
2897
0
  WINPR_ASSERT(ret);
2898
0
  wLog* log = scard_log();
2899
2900
0
  LONG status = 0;
2901
0
  UINT32 cReaders = ret->cReaders;
2902
0
  UINT32 index = 0;
2903
2904
0
  smartcard_trace_get_status_change_return(log, ret, unicode);
2905
0
  if ((ret->ReturnCode != SCARD_S_SUCCESS) && (ret->ReturnCode != SCARD_E_TIMEOUT))
2906
0
    cReaders = 0;
2907
0
  if (cReaders == SCARD_AUTOALLOCATE)
2908
0
    cReaders = 0;
2909
2910
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
2911
0
    return SCARD_E_NO_MEMORY;
2912
2913
0
  Stream_Write_UINT32(s, cReaders); /* cReaders (4 bytes) */
2914
0
  if (!smartcard_ndr_pointer_write(s, &index, cReaders))
2915
0
    return SCARD_E_NO_MEMORY;
2916
0
  status = smartcard_ndr_write_state(s, ret->rgReaderStates, cReaders, NDR_PTR_SIMPLE);
2917
0
  if (status != SCARD_S_SUCCESS)
2918
0
    return status;
2919
0
  return ret->ReturnCode;
2920
0
}
2921
2922
LONG smartcard_unpack_state_call(wStream* s, State_Call* call)
2923
0
{
2924
0
  UINT32 index = 0;
2925
0
  UINT32 pbContextNdrPtr = 0;
2926
2927
0
  wLog* log = scard_log();
2928
2929
0
  WINPR_ASSERT(call);
2930
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2931
0
                                                     &pbContextNdrPtr);
2932
0
  if (status != SCARD_S_SUCCESS)
2933
0
    return status;
2934
2935
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2936
0
  if (status != SCARD_S_SUCCESS)
2937
0
    return status;
2938
2939
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2940
0
    return STATUS_BUFFER_TOO_SMALL;
2941
2942
0
  Stream_Read_INT32(s, call->fpbAtrIsNULL); /* fpbAtrIsNULL (4 bytes) */
2943
0
  Stream_Read_UINT32(s, call->cbAtrLen);    /* cbAtrLen (4 bytes) */
2944
2945
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2946
0
                                                    &(call->handles.hContext));
2947
0
  if (status != SCARD_S_SUCCESS)
2948
0
    return status;
2949
2950
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2951
0
  if (status != SCARD_S_SUCCESS)
2952
0
    return status;
2953
2954
0
  return status;
2955
0
}
2956
2957
LONG smartcard_pack_state_return(wStream* s, const State_Return* ret)
2958
0
{
2959
0
  WINPR_ASSERT(ret);
2960
0
  wLog* log = scard_log();
2961
0
  LONG status = 0;
2962
0
  UINT32 cbAtrLen = ret->cbAtrLen;
2963
0
  UINT32 index = 0;
2964
2965
0
  smartcard_trace_state_return(log, ret);
2966
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
2967
0
    cbAtrLen = 0;
2968
0
  if (cbAtrLen == SCARD_AUTOALLOCATE)
2969
0
    cbAtrLen = 0;
2970
2971
0
  Stream_Write_UINT32(s, ret->dwState);    /* dwState (4 bytes) */
2972
0
  Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
2973
0
  Stream_Write_UINT32(s, cbAtrLen);        /* cbAtrLen (4 bytes) */
2974
0
  if (!smartcard_ndr_pointer_write(s, &index, cbAtrLen))
2975
0
    return SCARD_E_NO_MEMORY;
2976
0
  status = smartcard_ndr_write(s, ret->rgAtr, cbAtrLen, 1, NDR_PTR_SIMPLE);
2977
0
  if (status != SCARD_S_SUCCESS)
2978
0
    return status;
2979
0
  return ret->ReturnCode;
2980
0
}
2981
2982
LONG smartcard_unpack_status_call(wStream* s, Status_Call* call, BOOL unicode)
2983
0
{
2984
0
  UINT32 index = 0;
2985
0
  UINT32 pbContextNdrPtr = 0;
2986
2987
0
  WINPR_ASSERT(call);
2988
0
  wLog* log = scard_log();
2989
2990
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2991
0
                                                     &pbContextNdrPtr);
2992
0
  if (status != SCARD_S_SUCCESS)
2993
0
    return status;
2994
2995
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2996
0
  if (status != SCARD_S_SUCCESS)
2997
0
    return status;
2998
2999
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3000
0
    return STATUS_BUFFER_TOO_SMALL;
3001
3002
0
  Stream_Read_INT32(s, call->fmszReaderNamesIsNULL); /* fmszReaderNamesIsNULL (4 bytes) */
3003
0
  Stream_Read_UINT32(s, call->cchReaderLen);         /* cchReaderLen (4 bytes) */
3004
0
  Stream_Read_UINT32(s, call->cbAtrLen);             /* cbAtrLen (4 bytes) */
3005
3006
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3007
0
                                                    &(call->handles.hContext));
3008
0
  if (status != SCARD_S_SUCCESS)
3009
0
    return status;
3010
3011
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3012
0
  if (status != SCARD_S_SUCCESS)
3013
0
    return status;
3014
3015
0
  smartcard_trace_status_call(log, call, unicode);
3016
0
  return status;
3017
0
}
3018
3019
LONG smartcard_pack_status_call(wStream* s, const Status_Call* call, BOOL unicode)
3020
0
{
3021
0
  WINPR_ASSERT(call);
3022
0
  wLog* log = scard_log();
3023
0
  UINT32 index = 0;
3024
3025
0
  smartcard_trace_status_call(log, call, unicode);
3026
3027
0
  LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
3028
0
  if (status != SCARD_S_SUCCESS)
3029
0
    return status;
3030
3031
0
  status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
3032
0
  if (status != SCARD_S_SUCCESS)
3033
0
    return status;
3034
3035
0
  if (!Stream_EnsureRemainingCapacity(s, 12))
3036
0
    return SCARD_E_NO_MEMORY;
3037
3038
0
  Stream_Write_INT32(s, call->fmszReaderNamesIsNULL);
3039
0
  Stream_Write_UINT32(s, call->cchReaderLen);
3040
0
  Stream_Write_UINT32(s, call->cbAtrLen);
3041
3042
0
  status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
3043
0
  if (status != SCARD_S_SUCCESS)
3044
0
    return status;
3045
3046
0
  return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
3047
0
}
3048
3049
LONG smartcard_pack_status_return(wStream* s, const Status_Return* ret, BOOL unicode)
3050
0
{
3051
0
  WINPR_ASSERT(ret);
3052
0
  wLog* log = scard_log();
3053
3054
0
  LONG status = 0;
3055
0
  UINT32 index = 0;
3056
0
  UINT32 cBytes = ret->cBytes;
3057
3058
0
  smartcard_trace_status_return(log, ret, unicode);
3059
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
3060
0
    cBytes = 0;
3061
0
  if (cBytes == SCARD_AUTOALLOCATE)
3062
0
    cBytes = 0;
3063
3064
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
3065
0
    return SCARD_F_INTERNAL_ERROR;
3066
3067
0
  Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
3068
0
  if (!smartcard_ndr_pointer_write(s, &index, cBytes))
3069
0
    return SCARD_E_NO_MEMORY;
3070
3071
0
  if (!Stream_EnsureRemainingCapacity(s, 44))
3072
0
    return SCARD_F_INTERNAL_ERROR;
3073
3074
0
  Stream_Write_UINT32(s, ret->dwState);            /* dwState (4 bytes) */
3075
0
  Stream_Write_UINT32(s, ret->dwProtocol);         /* dwProtocol (4 bytes) */
3076
0
  Stream_Write(s, ret->pbAtr, sizeof(ret->pbAtr)); /* pbAtr (32 bytes) */
3077
0
  Stream_Write_UINT32(s, ret->cbAtrLen);           /* cbAtrLen (4 bytes) */
3078
0
  status = smartcard_ndr_write(s, ret->mszReaderNames, cBytes, 1, NDR_PTR_SIMPLE);
3079
0
  if (status != SCARD_S_SUCCESS)
3080
0
    return status;
3081
0
  return ret->ReturnCode;
3082
0
}
3083
3084
LONG smartcard_unpack_status_return(wStream* s, Status_Return* ret, BOOL unicode)
3085
0
{
3086
0
  WINPR_ASSERT(ret);
3087
0
  wLog* log = scard_log();
3088
0
  UINT32 index = 0;
3089
0
  UINT32 mszNdrPtr = 0;
3090
3091
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3092
0
    return STATUS_BUFFER_TOO_SMALL;
3093
3094
0
  const UINT32 cBytes = Stream_Get_UINT32(s);
3095
3096
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3097
0
    return ERROR_INVALID_DATA;
3098
3099
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 44))
3100
0
    return STATUS_BUFFER_TOO_SMALL;
3101
3102
0
  Stream_Read_UINT32(s, ret->dwState);
3103
0
  Stream_Read_UINT32(s, ret->dwProtocol);
3104
0
  Stream_Read(s, ret->pbAtr, sizeof(ret->pbAtr));
3105
0
  Stream_Read_UINT32(s, ret->cbAtrLen);
3106
3107
0
  if (ret->cbAtrLen > ARRAYSIZE(ret->pbAtr))
3108
0
  {
3109
0
    WLog_Print(log, WLOG_ERROR, "Status_Return::cbAtrLen %" PRIu32 " exceeds %" PRIuz,
3110
0
               ret->cbAtrLen, ARRAYSIZE(ret->pbAtr));
3111
0
    return SCARD_E_INVALID_ATR;
3112
0
  }
3113
3114
0
  if (mszNdrPtr)
3115
0
  {
3116
0
    LONG status = smartcard_ndr_read(log, s, &ret->mszReaderNames, cBytes, 1, NDR_PTR_SIMPLE);
3117
0
    if (status != SCARD_S_SUCCESS)
3118
0
      return status;
3119
0
    ret->cBytes = cBytes;
3120
0
  }
3121
3122
0
  smartcard_trace_status_return(log, ret, unicode);
3123
0
  return SCARD_S_SUCCESS;
3124
0
}
3125
3126
LONG smartcard_unpack_get_attrib_call(wStream* s, GetAttrib_Call* call)
3127
0
{
3128
0
  WINPR_ASSERT(call);
3129
0
  wLog* log = scard_log();
3130
0
  UINT32 index = 0;
3131
0
  UINT32 pbContextNdrPtr = 0;
3132
3133
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3134
0
                                                     &pbContextNdrPtr);
3135
0
  if (status != SCARD_S_SUCCESS)
3136
0
    return status;
3137
3138
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3139
0
  if (status != SCARD_S_SUCCESS)
3140
0
    return status;
3141
3142
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3143
0
    return STATUS_BUFFER_TOO_SMALL;
3144
3145
0
  Stream_Read_UINT32(s, call->dwAttrId);     /* dwAttrId (4 bytes) */
3146
0
  Stream_Read_INT32(s, call->fpbAttrIsNULL); /* fpbAttrIsNULL (4 bytes) */
3147
0
  Stream_Read_UINT32(s, call->cbAttrLen);    /* cbAttrLen (4 bytes) */
3148
3149
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3150
0
                                                    &(call->handles.hContext));
3151
0
  if (status != SCARD_S_SUCCESS)
3152
0
    return status;
3153
3154
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3155
0
  if (status != SCARD_S_SUCCESS)
3156
0
    return status;
3157
3158
0
  smartcard_trace_get_attrib_call(log, call);
3159
0
  return status;
3160
0
}
3161
3162
LONG smartcard_pack_get_attrib_return(wStream* s, const GetAttrib_Return* ret, DWORD dwAttrId,
3163
                                      DWORD cbAttrCallLen)
3164
0
{
3165
0
  WINPR_ASSERT(ret);
3166
0
  wLog* log = scard_log();
3167
0
  LONG status = 0;
3168
0
  UINT32 cbAttrLen = 0;
3169
0
  UINT32 index = 0;
3170
0
  smartcard_trace_get_attrib_return(log, ret, dwAttrId);
3171
3172
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
3173
0
    return SCARD_F_INTERNAL_ERROR;
3174
3175
0
  cbAttrLen = ret->cbAttrLen;
3176
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
3177
0
    cbAttrLen = 0;
3178
0
  if (cbAttrLen == SCARD_AUTOALLOCATE)
3179
0
    cbAttrLen = 0;
3180
3181
0
  if (ret->pbAttr)
3182
0
  {
3183
0
    if (cbAttrCallLen < cbAttrLen)
3184
0
      cbAttrLen = cbAttrCallLen;
3185
0
  }
3186
0
  Stream_Write_UINT32(s, cbAttrLen); /* cbAttrLen (4 bytes) */
3187
0
  if (!smartcard_ndr_pointer_write(s, &index, cbAttrLen))
3188
0
    return SCARD_E_NO_MEMORY;
3189
3190
0
  status = smartcard_ndr_write(s, ret->pbAttr, cbAttrLen, 1, NDR_PTR_SIMPLE);
3191
0
  if (status != SCARD_S_SUCCESS)
3192
0
    return status;
3193
0
  return ret->ReturnCode;
3194
0
}
3195
3196
LONG smartcard_unpack_control_call(wStream* s, Control_Call* call)
3197
0
{
3198
0
  WINPR_ASSERT(call);
3199
0
  wLog* log = scard_log();
3200
3201
0
  UINT32 index = 0;
3202
0
  UINT32 pvInBufferNdrPtr = 0;
3203
0
  UINT32 pbContextNdrPtr = 0;
3204
3205
0
  call->pvInBuffer = nullptr;
3206
3207
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3208
0
                                                     &pbContextNdrPtr);
3209
0
  if (status != SCARD_S_SUCCESS)
3210
0
    return status;
3211
3212
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3213
0
  if (status != SCARD_S_SUCCESS)
3214
0
    return status;
3215
3216
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 20))
3217
0
    return STATUS_BUFFER_TOO_SMALL;
3218
3219
0
  Stream_Read_UINT32(s, call->dwControlCode);  /* dwControlCode (4 bytes) */
3220
0
  const UINT32 cbInBufferSize = Stream_Get_UINT32(s); /* cbInBufferSize (4 bytes) */
3221
0
  if (!smartcard_ndr_pointer_read(log, s, &index,
3222
0
                                  &pvInBufferNdrPtr)) /* pvInBufferNdrPtr (4 bytes) */
3223
0
    return ERROR_INVALID_DATA;
3224
0
  Stream_Read_INT32(s, call->fpvOutBufferIsNULL); /* fpvOutBufferIsNULL (4 bytes) */
3225
0
  Stream_Read_UINT32(s, call->cbOutBufferSize);   /* cbOutBufferSize (4 bytes) */
3226
3227
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3228
0
                                                    &(call->handles.hContext));
3229
0
  if (status != SCARD_S_SUCCESS)
3230
0
    return status;
3231
3232
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3233
0
  if (status != SCARD_S_SUCCESS)
3234
0
    return status;
3235
3236
0
  if (pvInBufferNdrPtr)
3237
0
  {
3238
0
    status = smartcard_ndr_read(log, s, &call->pvInBuffer, cbInBufferSize, 1, NDR_PTR_SIMPLE);
3239
0
    if (status != SCARD_S_SUCCESS)
3240
0
      return status;
3241
0
    call->cbInBufferSize = cbInBufferSize;
3242
0
  }
3243
3244
0
  smartcard_trace_control_call(log, call);
3245
0
  return SCARD_S_SUCCESS;
3246
0
}
3247
3248
LONG smartcard_pack_control_return(wStream* s, const Control_Return* ret)
3249
0
{
3250
0
  WINPR_ASSERT(ret);
3251
0
  wLog* log = scard_log();
3252
3253
0
  LONG status = 0;
3254
0
  UINT32 cbDataLen = ret->cbOutBufferSize;
3255
0
  UINT32 index = 0;
3256
3257
0
  smartcard_trace_control_return(log, ret);
3258
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
3259
0
    cbDataLen = 0;
3260
0
  if (cbDataLen == SCARD_AUTOALLOCATE)
3261
0
    cbDataLen = 0;
3262
3263
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
3264
0
    return SCARD_F_INTERNAL_ERROR;
3265
3266
0
  Stream_Write_UINT32(s, cbDataLen); /* cbOutBufferSize (4 bytes) */
3267
0
  if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3268
0
    return SCARD_E_NO_MEMORY;
3269
3270
0
  status = smartcard_ndr_write(s, ret->pvOutBuffer, cbDataLen, 1, NDR_PTR_SIMPLE);
3271
0
  if (status != SCARD_S_SUCCESS)
3272
0
    return status;
3273
0
  return ret->ReturnCode;
3274
0
}
3275
3276
LONG smartcard_unpack_transmit_call(wStream* s, Transmit_Call* call)
3277
0
{
3278
0
  UINT32 length = 0;
3279
0
  BYTE* pbExtraBytes = nullptr;
3280
0
  UINT32 pbExtraBytesNdrPtr = 0;
3281
0
  UINT32 pbSendBufferNdrPtr = 0;
3282
0
  UINT32 pioRecvPciNdrPtr = 0;
3283
0
  SCardIO_Request ioSendPci;
3284
0
  SCardIO_Request ioRecvPci;
3285
0
  UINT32 index = 0;
3286
0
  UINT32 pbContextNdrPtr = 0;
3287
3288
0
  WINPR_ASSERT(call);
3289
0
  wLog* log = scard_log();
3290
3291
0
  call->pioSendPci = nullptr;
3292
0
  call->pioRecvPci = nullptr;
3293
0
  call->pbSendBuffer = nullptr;
3294
3295
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3296
0
                                                     &pbContextNdrPtr);
3297
0
  if (status != SCARD_S_SUCCESS)
3298
0
    return status;
3299
3300
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3301
0
  if (status != SCARD_S_SUCCESS)
3302
0
    return status;
3303
3304
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 32))
3305
0
    return STATUS_BUFFER_TOO_SMALL;
3306
3307
0
  Stream_Read_UINT32(s, ioSendPci.dwProtocol);   /* dwProtocol (4 bytes) */
3308
0
  Stream_Read_UINT32(s, ioSendPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
3309
0
  if (!smartcard_ndr_pointer_read(log, s, &index,
3310
0
                                  &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
3311
0
    return ERROR_INVALID_DATA;
3312
3313
0
  const UINT32 cbSendLength = Stream_Get_UINT32(s); /* cbSendLength (4 bytes) */
3314
0
  if (!smartcard_ndr_pointer_read(log, s, &index,
3315
0
                                  &pbSendBufferNdrPtr)) /* pbSendBufferNdrPtr (4 bytes) */
3316
0
    return ERROR_INVALID_DATA;
3317
3318
0
  if (!smartcard_ndr_pointer_read(log, s, &index,
3319
0
                                  &pioRecvPciNdrPtr)) /* pioRecvPciNdrPtr (4 bytes) */
3320
0
    return ERROR_INVALID_DATA;
3321
3322
0
  Stream_Read_INT32(s, call->fpbRecvBufferIsNULL); /* fpbRecvBufferIsNULL (4 bytes) */
3323
0
  Stream_Read_UINT32(s, call->cbRecvLength);       /* cbRecvLength (4 bytes) */
3324
3325
0
  if (ioSendPci.cbExtraBytes > 1024)
3326
0
  {
3327
0
    WLog_Print(log, WLOG_WARN,
3328
0
               "Transmit_Call ioSendPci.cbExtraBytes is out of bounds: %" PRIu32 " (max: 1024)",
3329
0
               ioSendPci.cbExtraBytes);
3330
0
    return STATUS_INVALID_PARAMETER;
3331
0
  }
3332
3333
0
  if (cbSendLength > 66560)
3334
0
  {
3335
0
    WLog_Print(log, WLOG_WARN,
3336
0
               "Transmit_Call cbSendLength is out of bounds: %" PRIu32 " (max: 66560)",
3337
0
               ioSendPci.cbExtraBytes);
3338
0
    return STATUS_INVALID_PARAMETER;
3339
0
  }
3340
3341
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3342
0
                                                    &(call->handles.hContext));
3343
0
  if (status != SCARD_S_SUCCESS)
3344
0
    return status;
3345
3346
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3347
0
  if (status != SCARD_S_SUCCESS)
3348
0
    return status;
3349
3350
0
  if (ioSendPci.cbExtraBytes && !pbExtraBytesNdrPtr)
3351
0
  {
3352
0
    WLog_Print(
3353
0
        log, WLOG_WARN,
3354
0
        "Transmit_Call ioSendPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
3355
0
    return STATUS_INVALID_PARAMETER;
3356
0
  }
3357
3358
0
  if (pbExtraBytesNdrPtr)
3359
0
  {
3360
    // TODO: Use unified pointer reading
3361
0
    if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3362
0
      return STATUS_BUFFER_TOO_SMALL;
3363
3364
0
    Stream_Read_UINT32(s, length); /* Length (4 bytes) */
3365
3366
0
    if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ioSendPci.cbExtraBytes))
3367
0
      return STATUS_BUFFER_TOO_SMALL;
3368
3369
0
    ioSendPci.pbExtraBytes = Stream_Pointer(s);
3370
0
    call->pioSendPci =
3371
0
        (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioSendPci.cbExtraBytes);
3372
3373
0
    if (!call->pioSendPci)
3374
0
    {
3375
0
      WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioSendPci)");
3376
0
      return STATUS_NO_MEMORY;
3377
0
    }
3378
3379
0
    call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
3380
0
    call->pioSendPci->cbPciLength = (DWORD)(ioSendPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
3381
0
    pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
3382
0
    Stream_Read(s, pbExtraBytes, ioSendPci.cbExtraBytes);
3383
0
    if (smartcard_unpack_read_size_align(s, ioSendPci.cbExtraBytes, 4) < 0)
3384
0
      return STATUS_INVALID_PARAMETER;
3385
0
  }
3386
0
  else
3387
0
  {
3388
0
    call->pioSendPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
3389
3390
0
    if (!call->pioSendPci)
3391
0
    {
3392
0
      WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioSendPci)");
3393
0
      return STATUS_NO_MEMORY;
3394
0
    }
3395
3396
0
    call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
3397
0
    call->pioSendPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
3398
0
  }
3399
3400
0
  if (pbSendBufferNdrPtr)
3401
0
  {
3402
0
    status = smartcard_ndr_read(log, s, &call->pbSendBuffer, cbSendLength, 1, NDR_PTR_SIMPLE);
3403
0
    if (status != SCARD_S_SUCCESS)
3404
0
      return status;
3405
0
    call->cbSendLength = cbSendLength;
3406
0
  }
3407
3408
0
  if (pioRecvPciNdrPtr)
3409
0
  {
3410
0
    if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3411
0
      return STATUS_BUFFER_TOO_SMALL;
3412
3413
0
    Stream_Read_UINT32(s, ioRecvPci.dwProtocol);   /* dwProtocol (4 bytes) */
3414
0
    Stream_Read_UINT32(s, ioRecvPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
3415
0
    if (!smartcard_ndr_pointer_read(log, s, &index,
3416
0
                                    &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
3417
0
      return ERROR_INVALID_DATA;
3418
3419
0
    if (ioRecvPci.cbExtraBytes && !pbExtraBytesNdrPtr)
3420
0
    {
3421
0
      WLog_Print(
3422
0
          log, WLOG_WARN,
3423
0
          "Transmit_Call ioRecvPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
3424
0
      return STATUS_INVALID_PARAMETER;
3425
0
    }
3426
3427
0
    if (pbExtraBytesNdrPtr)
3428
0
    {
3429
      // TODO: Unify ndr pointer reading
3430
0
      if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3431
0
        return STATUS_BUFFER_TOO_SMALL;
3432
3433
0
      Stream_Read_UINT32(s, length); /* Length (4 bytes) */
3434
3435
0
      if (ioRecvPci.cbExtraBytes > 1024)
3436
0
      {
3437
0
        WLog_Print(log, WLOG_WARN,
3438
0
                   "Transmit_Call ioRecvPci.cbExtraBytes is out of bounds: %" PRIu32
3439
0
                   " (max: 1024)",
3440
0
                   ioRecvPci.cbExtraBytes);
3441
0
        return STATUS_INVALID_PARAMETER;
3442
0
      }
3443
3444
0
      if (length != ioRecvPci.cbExtraBytes)
3445
0
      {
3446
0
        WLog_Print(log, WLOG_WARN,
3447
0
                   "Transmit_Call unexpected length: Actual: %" PRIu32
3448
0
                   ", Expected: %" PRIu32 " (ioRecvPci.cbExtraBytes)",
3449
0
                   length, ioRecvPci.cbExtraBytes);
3450
0
        return STATUS_INVALID_PARAMETER;
3451
0
      }
3452
3453
0
      if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ioRecvPci.cbExtraBytes))
3454
0
        return STATUS_BUFFER_TOO_SMALL;
3455
3456
0
      ioRecvPci.pbExtraBytes = Stream_Pointer(s);
3457
0
      call->pioRecvPci =
3458
0
          (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioRecvPci.cbExtraBytes);
3459
3460
0
      if (!call->pioRecvPci)
3461
0
      {
3462
0
        WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioRecvPci)");
3463
0
        return STATUS_NO_MEMORY;
3464
0
      }
3465
3466
0
      call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
3467
0
      call->pioRecvPci->cbPciLength =
3468
0
          (DWORD)(ioRecvPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
3469
0
      pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
3470
0
      Stream_Read(s, pbExtraBytes, ioRecvPci.cbExtraBytes);
3471
0
      if (smartcard_unpack_read_size_align(s, ioRecvPci.cbExtraBytes, 4) < 0)
3472
0
        return STATUS_INVALID_PARAMETER;
3473
0
    }
3474
0
    else
3475
0
    {
3476
0
      call->pioRecvPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
3477
3478
0
      if (!call->pioRecvPci)
3479
0
      {
3480
0
        WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioRecvPci)");
3481
0
        return STATUS_NO_MEMORY;
3482
0
      }
3483
3484
0
      call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
3485
0
      call->pioRecvPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
3486
0
    }
3487
0
  }
3488
3489
0
  smartcard_trace_transmit_call(log, call);
3490
0
  return SCARD_S_SUCCESS;
3491
0
}
3492
3493
LONG smartcard_pack_transmit_return(wStream* s, const Transmit_Return* ret)
3494
0
{
3495
0
  WINPR_ASSERT(ret);
3496
0
  wLog* log = scard_log();
3497
3498
0
  LONG status = 0;
3499
0
  UINT32 index = 0;
3500
0
  LONG error = 0;
3501
0
  UINT32 cbRecvLength = ret->cbRecvLength;
3502
0
  UINT32 cbRecvPci = ret->pioRecvPci ? ret->pioRecvPci->cbPciLength : 0;
3503
3504
0
  smartcard_trace_transmit_return(log, ret);
3505
3506
0
  if (!ret->pbRecvBuffer)
3507
0
    cbRecvLength = 0;
3508
3509
0
  if (!smartcard_ndr_pointer_write(s, &index, cbRecvPci))
3510
0
    return SCARD_E_NO_MEMORY;
3511
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
3512
0
    return SCARD_E_NO_MEMORY;
3513
0
  Stream_Write_UINT32(s, cbRecvLength); /* cbRecvLength (4 bytes) */
3514
0
  if (!smartcard_ndr_pointer_write(s, &index, cbRecvLength))
3515
0
    return SCARD_E_NO_MEMORY;
3516
3517
0
  if (ret->pioRecvPci)
3518
0
  {
3519
0
    UINT32 cbExtraBytes = (UINT32)(ret->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
3520
0
    BYTE* pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
3521
3522
0
    if (!Stream_EnsureRemainingCapacity(s, cbExtraBytes + 16))
3523
0
    {
3524
0
      WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3525
0
      return SCARD_F_INTERNAL_ERROR;
3526
0
    }
3527
3528
0
    Stream_Write_UINT32(s, ret->pioRecvPci->dwProtocol); /* dwProtocol (4 bytes) */
3529
0
    Stream_Write_UINT32(s, cbExtraBytes);                /* cbExtraBytes (4 bytes) */
3530
0
    if (!smartcard_ndr_pointer_write(s, &index, cbExtraBytes))
3531
0
      return SCARD_E_NO_MEMORY;
3532
0
    error = smartcard_ndr_write(s, pbExtraBytes, cbExtraBytes, 1, NDR_PTR_SIMPLE);
3533
0
    if (error)
3534
0
      return error;
3535
0
  }
3536
3537
0
  status = smartcard_ndr_write(s, ret->pbRecvBuffer, ret->cbRecvLength, 1, NDR_PTR_SIMPLE);
3538
0
  if (status != SCARD_S_SUCCESS)
3539
0
    return status;
3540
0
  return ret->ReturnCode;
3541
0
}
3542
3543
LONG smartcard_unpack_locate_cards_by_atr_a_call(wStream* s, LocateCardsByATRA_Call* call)
3544
0
{
3545
0
  UINT32 rgReaderStatesNdrPtr = 0;
3546
0
  UINT32 rgAtrMasksNdrPtr = 0;
3547
0
  UINT32 index = 0;
3548
0
  UINT32 pbContextNdrPtr = 0;
3549
3550
0
  WINPR_ASSERT(call);
3551
0
  wLog* log = scard_log();
3552
3553
0
  call->rgReaderStates = nullptr;
3554
3555
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3556
0
                                                     &pbContextNdrPtr);
3557
0
  if (status != SCARD_S_SUCCESS)
3558
0
    return status;
3559
3560
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3561
0
    return STATUS_BUFFER_TOO_SMALL;
3562
3563
0
  Stream_Read_UINT32(s, call->cAtrs);
3564
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &rgAtrMasksNdrPtr))
3565
0
    return ERROR_INVALID_DATA;
3566
0
  const UINT32 cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
3567
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &rgReaderStatesNdrPtr))
3568
0
    return ERROR_INVALID_DATA;
3569
3570
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3571
0
                                                    &(call->handles.hContext));
3572
0
  if (status != SCARD_S_SUCCESS)
3573
0
    return status;
3574
3575
0
  if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3576
0
  {
3577
0
    WLog_Print(log, WLOG_WARN,
3578
0
               "LocateCardsByATRA_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3579
0
               ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3580
0
               rgAtrMasksNdrPtr, call->cAtrs);
3581
0
    return STATUS_INVALID_PARAMETER;
3582
0
  }
3583
3584
0
  if (rgAtrMasksNdrPtr)
3585
0
  {
3586
0
    status = smartcard_ndr_read_atrmask(log, s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3587
0
    if (status != SCARD_S_SUCCESS)
3588
0
      return status;
3589
0
  }
3590
3591
0
  if (rgReaderStatesNdrPtr)
3592
0
  {
3593
0
    status = smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, cReaders, &index);
3594
0
    if (status != SCARD_S_SUCCESS)
3595
0
      return status;
3596
0
    call->cReaders = cReaders;
3597
0
  }
3598
3599
0
  smartcard_trace_locate_cards_by_atr_a_call(log, call);
3600
0
  return SCARD_S_SUCCESS;
3601
0
}
3602
3603
LONG smartcard_unpack_context_and_two_strings_a_call(wStream* s, ContextAndTwoStringA_Call* call)
3604
0
{
3605
0
  UINT32 sz1NdrPtr = 0;
3606
0
  UINT32 sz2NdrPtr = 0;
3607
0
  UINT32 index = 0;
3608
0
  UINT32 pbContextNdrPtr = 0;
3609
3610
0
  WINPR_ASSERT(call);
3611
0
  wLog* log = scard_log();
3612
3613
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3614
0
                                                     &pbContextNdrPtr);
3615
0
  if (status != SCARD_S_SUCCESS)
3616
0
    return status;
3617
3618
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3619
0
    return ERROR_INVALID_DATA;
3620
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3621
0
    return ERROR_INVALID_DATA;
3622
3623
0
  status =
3624
0
      smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &call->handles.hContext);
3625
0
  if (status != SCARD_S_SUCCESS)
3626
0
    return status;
3627
3628
0
  if (sz1NdrPtr)
3629
0
  {
3630
0
    status = smartcard_ndr_read_a(log, s, &call->sz1, NDR_PTR_FULL);
3631
0
    if (status != SCARD_S_SUCCESS)
3632
0
      return status;
3633
0
  }
3634
0
  if (sz2NdrPtr)
3635
0
  {
3636
0
    status = smartcard_ndr_read_a(log, s, &call->sz2, NDR_PTR_FULL);
3637
0
    if (status != SCARD_S_SUCCESS)
3638
0
      return status;
3639
0
  }
3640
0
  smartcard_trace_context_and_two_strings_a_call(log, call);
3641
0
  return SCARD_S_SUCCESS;
3642
0
}
3643
3644
LONG smartcard_unpack_context_and_two_strings_w_call(wStream* s, ContextAndTwoStringW_Call* call)
3645
0
{
3646
0
  UINT32 sz1NdrPtr = 0;
3647
0
  UINT32 sz2NdrPtr = 0;
3648
0
  UINT32 index = 0;
3649
0
  UINT32 pbContextNdrPtr = 0;
3650
3651
0
  WINPR_ASSERT(call);
3652
0
  wLog* log = scard_log();
3653
3654
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3655
0
                                                     &pbContextNdrPtr);
3656
0
  if (status != SCARD_S_SUCCESS)
3657
0
    return status;
3658
3659
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3660
0
    return ERROR_INVALID_DATA;
3661
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3662
0
    return ERROR_INVALID_DATA;
3663
3664
0
  status =
3665
0
      smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &call->handles.hContext);
3666
0
  if (status != SCARD_S_SUCCESS)
3667
0
    return status;
3668
3669
0
  if (sz1NdrPtr)
3670
0
  {
3671
0
    status = smartcard_ndr_read_w(log, s, &call->sz1, NDR_PTR_FULL);
3672
0
    if (status != SCARD_S_SUCCESS)
3673
0
      return status;
3674
0
  }
3675
0
  if (sz2NdrPtr)
3676
0
  {
3677
0
    status = smartcard_ndr_read_w(log, s, &call->sz2, NDR_PTR_FULL);
3678
0
    if (status != SCARD_S_SUCCESS)
3679
0
      return status;
3680
0
  }
3681
0
  smartcard_trace_context_and_two_strings_w_call(log, call);
3682
0
  return SCARD_S_SUCCESS;
3683
0
}
3684
3685
LONG smartcard_unpack_locate_cards_a_call(wStream* s, LocateCardsA_Call* call)
3686
0
{
3687
0
  UINT32 sz1NdrPtr = 0;
3688
0
  UINT32 sz2NdrPtr = 0;
3689
0
  UINT32 index = 0;
3690
0
  UINT32 pbContextNdrPtr = 0;
3691
3692
0
  WINPR_ASSERT(call);
3693
0
  wLog* log = scard_log();
3694
3695
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3696
0
                                                     &pbContextNdrPtr);
3697
0
  if (status != SCARD_S_SUCCESS)
3698
0
    return status;
3699
3700
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3701
0
    return STATUS_BUFFER_TOO_SMALL;
3702
3703
0
  const UINT32 cBytes = Stream_Get_UINT32(s);
3704
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3705
0
    return ERROR_INVALID_DATA;
3706
3707
0
  const UINT32 cReaders = Stream_Get_UINT32(s);
3708
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3709
0
    return ERROR_INVALID_DATA;
3710
3711
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3712
0
                                                    &(call->handles.hContext));
3713
0
  if (status != SCARD_S_SUCCESS)
3714
0
    return status;
3715
3716
0
  if (sz1NdrPtr)
3717
0
  {
3718
0
    status = smartcard_ndr_read_fixed_string_a(log, s, &call->mszCards, cBytes, NDR_PTR_SIMPLE);
3719
0
    if (status != SCARD_S_SUCCESS)
3720
0
      return status;
3721
0
    call->cBytes = cBytes;
3722
0
  }
3723
0
  if (sz2NdrPtr)
3724
0
  {
3725
0
    status = smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, cReaders, &index);
3726
0
    if (status != SCARD_S_SUCCESS)
3727
0
      return status;
3728
0
    call->cReaders = cReaders;
3729
0
  }
3730
0
  smartcard_trace_locate_cards_a_call(log, call);
3731
0
  return SCARD_S_SUCCESS;
3732
0
}
3733
3734
LONG smartcard_unpack_locate_cards_w_call(wStream* s, LocateCardsW_Call* call)
3735
0
{
3736
0
  UINT32 sz1NdrPtr = 0;
3737
0
  UINT32 sz2NdrPtr = 0;
3738
0
  UINT32 index = 0;
3739
0
  UINT32 pbContextNdrPtr = 0;
3740
3741
0
  WINPR_ASSERT(call);
3742
0
  wLog* log = scard_log();
3743
3744
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3745
0
                                                     &pbContextNdrPtr);
3746
0
  if (status != SCARD_S_SUCCESS)
3747
0
    return status;
3748
3749
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3750
0
    return STATUS_BUFFER_TOO_SMALL;
3751
3752
0
  const UINT32 cBytes = Stream_Get_UINT32(s);
3753
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3754
0
    return ERROR_INVALID_DATA;
3755
3756
0
  const UINT32 cReaders = Stream_Get_UINT32(s);
3757
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3758
0
    return ERROR_INVALID_DATA;
3759
3760
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3761
0
                                                    &(call->handles.hContext));
3762
0
  if (status != SCARD_S_SUCCESS)
3763
0
    return status;
3764
3765
0
  if (sz1NdrPtr)
3766
0
  {
3767
0
    status = smartcard_ndr_read_fixed_string_w(log, s, &call->mszCards, cBytes, NDR_PTR_SIMPLE);
3768
0
    if (status != SCARD_S_SUCCESS)
3769
0
      return status;
3770
0
    call->cBytes = cBytes;
3771
0
  }
3772
0
  if (sz2NdrPtr)
3773
0
  {
3774
0
    status = smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, cReaders, &index);
3775
0
    if (status != SCARD_S_SUCCESS)
3776
0
      return status;
3777
0
    call->cReaders = cReaders;
3778
0
  }
3779
0
  smartcard_trace_locate_cards_w_call(log, call);
3780
0
  return SCARD_S_SUCCESS;
3781
0
}
3782
3783
LONG smartcard_unpack_set_attrib_call(wStream* s, SetAttrib_Call* call)
3784
0
{
3785
0
  UINT32 index = 0;
3786
0
  UINT32 ndrPtr = 0;
3787
0
  UINT32 pbContextNdrPtr = 0;
3788
3789
0
  WINPR_ASSERT(call);
3790
0
  wLog* log = scard_log();
3791
3792
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3793
0
                                                     &pbContextNdrPtr);
3794
0
  if (status != SCARD_S_SUCCESS)
3795
0
    return status;
3796
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3797
0
  if (status != SCARD_S_SUCCESS)
3798
0
    return status;
3799
3800
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3801
0
    return STATUS_BUFFER_TOO_SMALL;
3802
0
  Stream_Read_UINT32(s, call->dwAttrId);
3803
0
  Stream_Read_UINT32(s, call->cbAttrLen);
3804
3805
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
3806
0
    return ERROR_INVALID_DATA;
3807
3808
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3809
0
                                                    &(call->handles.hContext));
3810
0
  if (status != SCARD_S_SUCCESS)
3811
0
    return status;
3812
3813
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3814
0
  if (status != SCARD_S_SUCCESS)
3815
0
    return status;
3816
3817
0
  if (ndrPtr)
3818
0
  {
3819
0
    size_t len = 0;
3820
0
    status = smartcard_ndr_read_ex(log, s, &call->pbAttr, 0, 1, NDR_PTR_SIMPLE, &len);
3821
0
    if (status != SCARD_S_SUCCESS)
3822
0
      return status;
3823
0
    if (call->cbAttrLen > len)
3824
0
      call->cbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, len);
3825
0
  }
3826
0
  else
3827
0
    call->cbAttrLen = 0;
3828
0
  smartcard_trace_set_attrib_call(log, call);
3829
0
  return SCARD_S_SUCCESS;
3830
0
}
3831
3832
LONG smartcard_pack_set_attrib_call(wStream* s, const SetAttrib_Call* call)
3833
0
{
3834
0
  WINPR_ASSERT(call);
3835
0
  wLog* log = scard_log();
3836
0
  UINT32 index = 0;
3837
3838
0
  smartcard_trace_set_attrib_call(log, call);
3839
3840
0
  LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
3841
0
  if (status != SCARD_S_SUCCESS)
3842
0
    return status;
3843
3844
0
  status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
3845
0
  if (status != SCARD_S_SUCCESS)
3846
0
    return status;
3847
3848
0
  if (!Stream_EnsureRemainingCapacity(s, 8))
3849
0
    return SCARD_E_NO_MEMORY;
3850
3851
0
  Stream_Write_UINT32(s, call->dwAttrId);
3852
0
  Stream_Write_UINT32(s, call->cbAttrLen);
3853
3854
0
  if (!smartcard_ndr_pointer_write(s, &index, call->cbAttrLen))
3855
0
    return SCARD_E_NO_MEMORY;
3856
3857
0
  status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
3858
0
  if (status != SCARD_S_SUCCESS)
3859
0
    return status;
3860
3861
0
  status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
3862
0
  if (status != SCARD_S_SUCCESS)
3863
0
    return status;
3864
3865
0
  status = smartcard_ndr_write(s, call->pbAttr, call->cbAttrLen, 1, NDR_PTR_SIMPLE);
3866
0
  if (status != SCARD_S_SUCCESS)
3867
0
    return status;
3868
3869
0
  return SCARD_S_SUCCESS;
3870
0
}
3871
3872
LONG smartcard_unpack_locate_cards_by_atr_w_call(wStream* s, LocateCardsByATRW_Call* call)
3873
0
{
3874
0
  UINT32 rgReaderStatesNdrPtr = 0;
3875
0
  UINT32 rgAtrMasksNdrPtr = 0;
3876
0
  UINT32 index = 0;
3877
0
  UINT32 pbContextNdrPtr = 0;
3878
3879
0
  WINPR_ASSERT(call);
3880
0
  wLog* log = scard_log();
3881
3882
0
  call->rgReaderStates = nullptr;
3883
3884
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3885
0
                                                     &pbContextNdrPtr);
3886
0
  if (status != SCARD_S_SUCCESS)
3887
0
    return status;
3888
3889
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3890
0
    return STATUS_BUFFER_TOO_SMALL;
3891
3892
0
  Stream_Read_UINT32(s, call->cAtrs);
3893
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &rgAtrMasksNdrPtr))
3894
0
    return ERROR_INVALID_DATA;
3895
3896
0
  const UINT32 cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
3897
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &rgReaderStatesNdrPtr))
3898
0
    return ERROR_INVALID_DATA;
3899
3900
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3901
0
                                                    &(call->handles.hContext));
3902
0
  if (status != SCARD_S_SUCCESS)
3903
0
    return status;
3904
3905
0
  if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3906
0
  {
3907
0
    WLog_Print(log, WLOG_WARN,
3908
0
               "LocateCardsByATRW_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3909
0
               ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3910
0
               rgAtrMasksNdrPtr, call->cAtrs);
3911
0
    return STATUS_INVALID_PARAMETER;
3912
0
  }
3913
3914
0
  if (rgAtrMasksNdrPtr)
3915
0
  {
3916
0
    status = smartcard_ndr_read_atrmask(log, s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3917
0
    if (status != SCARD_S_SUCCESS)
3918
0
      return status;
3919
0
  }
3920
3921
0
  if (rgReaderStatesNdrPtr)
3922
0
  {
3923
0
    status = smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, cReaders, &index);
3924
0
    if (status != SCARD_S_SUCCESS)
3925
0
      return status;
3926
0
    call->cReaders = cReaders;
3927
0
  }
3928
3929
0
  smartcard_trace_locate_cards_by_atr_w_call(log, call);
3930
0
  return SCARD_S_SUCCESS;
3931
0
}
3932
3933
LONG smartcard_unpack_read_cache_a_call(wStream* s, ReadCacheA_Call* call)
3934
0
{
3935
0
  UINT32 mszNdrPtr = 0;
3936
0
  UINT32 contextNdrPtr = 0;
3937
0
  UINT32 index = 0;
3938
0
  UINT32 pbContextNdrPtr = 0;
3939
3940
0
  WINPR_ASSERT(call);
3941
0
  wLog* log = scard_log();
3942
3943
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3944
0
    return ERROR_INVALID_DATA;
3945
3946
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3947
0
                                                     &index, &pbContextNdrPtr);
3948
0
  if (status != SCARD_S_SUCCESS)
3949
0
    return status;
3950
3951
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3952
0
    return ERROR_INVALID_DATA;
3953
3954
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3955
0
    return STATUS_BUFFER_TOO_SMALL;
3956
0
  Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3957
0
  Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
3958
0
  Stream_Read_UINT32(s, call->Common.cbDataLen);
3959
3960
0
  call->szLookupName = nullptr;
3961
0
  if (mszNdrPtr)
3962
0
  {
3963
0
    status = smartcard_ndr_read_a(log, s, &call->szLookupName, NDR_PTR_FULL);
3964
0
    if (status != SCARD_S_SUCCESS)
3965
0
      return status;
3966
0
  }
3967
3968
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3969
0
                                                    &call->Common.handles.hContext);
3970
0
  if (status != SCARD_S_SUCCESS)
3971
0
    return status;
3972
3973
0
  if (contextNdrPtr)
3974
0
  {
3975
0
    status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3976
0
    if (status != SCARD_S_SUCCESS)
3977
0
      return status;
3978
0
  }
3979
0
  smartcard_trace_read_cache_a_call(log, call);
3980
0
  return SCARD_S_SUCCESS;
3981
0
}
3982
3983
LONG smartcard_unpack_read_cache_w_call(wStream* s, ReadCacheW_Call* call)
3984
0
{
3985
0
  UINT32 mszNdrPtr = 0;
3986
0
  UINT32 contextNdrPtr = 0;
3987
0
  UINT32 index = 0;
3988
0
  UINT32 pbContextNdrPtr = 0;
3989
3990
0
  WINPR_ASSERT(call);
3991
0
  wLog* log = scard_log();
3992
3993
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3994
0
    return ERROR_INVALID_DATA;
3995
3996
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3997
0
                                                     &index, &pbContextNdrPtr);
3998
0
  if (status != SCARD_S_SUCCESS)
3999
0
    return status;
4000
4001
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
4002
0
    return ERROR_INVALID_DATA;
4003
4004
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
4005
0
    return STATUS_BUFFER_TOO_SMALL;
4006
0
  Stream_Read_UINT32(s, call->Common.FreshnessCounter);
4007
0
  Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
4008
0
  Stream_Read_UINT32(s, call->Common.cbDataLen);
4009
4010
0
  call->szLookupName = nullptr;
4011
0
  if (mszNdrPtr)
4012
0
  {
4013
0
    status = smartcard_ndr_read_w(log, s, &call->szLookupName, NDR_PTR_FULL);
4014
0
    if (status != SCARD_S_SUCCESS)
4015
0
      return status;
4016
0
  }
4017
4018
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4019
0
                                                    &call->Common.handles.hContext);
4020
0
  if (status != SCARD_S_SUCCESS)
4021
0
    return status;
4022
4023
0
  if (contextNdrPtr)
4024
0
  {
4025
0
    status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
4026
0
    if (status != SCARD_S_SUCCESS)
4027
0
      return status;
4028
0
  }
4029
0
  smartcard_trace_read_cache_w_call(log, call);
4030
0
  return SCARD_S_SUCCESS;
4031
0
}
4032
4033
LONG smartcard_unpack_write_cache_a_call(wStream* s, WriteCacheA_Call* call)
4034
0
{
4035
0
  UINT32 mszNdrPtr = 0;
4036
0
  UINT32 contextNdrPtr = 0;
4037
0
  UINT32 pbDataNdrPtr = 0;
4038
0
  UINT32 index = 0;
4039
0
  UINT32 pbContextNdrPtr = 0;
4040
4041
0
  WINPR_ASSERT(call);
4042
0
  wLog* log = scard_log();
4043
4044
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
4045
0
    return ERROR_INVALID_DATA;
4046
4047
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
4048
0
                                                     &index, &pbContextNdrPtr);
4049
0
  if (status != SCARD_S_SUCCESS)
4050
0
    return status;
4051
4052
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
4053
0
    return ERROR_INVALID_DATA;
4054
4055
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
4056
0
    return STATUS_BUFFER_TOO_SMALL;
4057
4058
0
  Stream_Read_UINT32(s, call->Common.FreshnessCounter);
4059
0
  const UINT32 cbDataLen = Stream_Get_UINT32(s);
4060
4061
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &pbDataNdrPtr))
4062
0
    return ERROR_INVALID_DATA;
4063
4064
0
  call->szLookupName = nullptr;
4065
0
  if (mszNdrPtr)
4066
0
  {
4067
0
    status = smartcard_ndr_read_a(log, s, &call->szLookupName, NDR_PTR_FULL);
4068
0
    if (status != SCARD_S_SUCCESS)
4069
0
      return status;
4070
0
  }
4071
4072
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4073
0
                                                    &call->Common.handles.hContext);
4074
0
  if (status != SCARD_S_SUCCESS)
4075
0
    return status;
4076
4077
0
  call->Common.CardIdentifier = nullptr;
4078
0
  if (contextNdrPtr)
4079
0
  {
4080
0
    status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
4081
0
    if (status != SCARD_S_SUCCESS)
4082
0
      return status;
4083
0
  }
4084
4085
0
  call->Common.pbData = nullptr;
4086
0
  if (pbDataNdrPtr)
4087
0
  {
4088
0
    status = smartcard_ndr_read(log, s, &call->Common.pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4089
0
    if (status != SCARD_S_SUCCESS)
4090
0
      return status;
4091
0
    call->Common.cbDataLen = cbDataLen;
4092
0
  }
4093
0
  smartcard_trace_write_cache_a_call(log, call);
4094
0
  return SCARD_S_SUCCESS;
4095
0
}
4096
4097
LONG smartcard_unpack_write_cache_w_call(wStream* s, WriteCacheW_Call* call)
4098
0
{
4099
0
  UINT32 mszNdrPtr = 0;
4100
0
  UINT32 contextNdrPtr = 0;
4101
0
  UINT32 pbDataNdrPtr = 0;
4102
0
  UINT32 index = 0;
4103
0
  UINT32 pbContextNdrPtr = 0;
4104
4105
0
  WINPR_ASSERT(call);
4106
0
  wLog* log = scard_log();
4107
4108
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
4109
0
    return ERROR_INVALID_DATA;
4110
4111
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
4112
0
                                                     &index, &pbContextNdrPtr);
4113
0
  if (status != SCARD_S_SUCCESS)
4114
0
    return status;
4115
4116
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
4117
0
    return ERROR_INVALID_DATA;
4118
4119
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
4120
0
    return STATUS_BUFFER_TOO_SMALL;
4121
0
  Stream_Read_UINT32(s, call->Common.FreshnessCounter);
4122
0
  const UINT32 cbDataLen = Stream_Get_UINT32(s);
4123
4124
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &pbDataNdrPtr))
4125
0
    return ERROR_INVALID_DATA;
4126
4127
0
  call->szLookupName = nullptr;
4128
0
  if (mszNdrPtr)
4129
0
  {
4130
0
    status = smartcard_ndr_read_w(log, s, &call->szLookupName, NDR_PTR_FULL);
4131
0
    if (status != SCARD_S_SUCCESS)
4132
0
      return status;
4133
0
  }
4134
4135
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4136
0
                                                    &call->Common.handles.hContext);
4137
0
  if (status != SCARD_S_SUCCESS)
4138
0
    return status;
4139
4140
0
  call->Common.CardIdentifier = nullptr;
4141
0
  if (contextNdrPtr)
4142
0
  {
4143
0
    status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
4144
0
    if (status != SCARD_S_SUCCESS)
4145
0
      return status;
4146
0
  }
4147
4148
0
  call->Common.pbData = nullptr;
4149
0
  if (pbDataNdrPtr)
4150
0
  {
4151
0
    status = smartcard_ndr_read(log, s, &call->Common.pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4152
0
    if (status != SCARD_S_SUCCESS)
4153
0
      return status;
4154
0
    call->Common.cbDataLen = cbDataLen;
4155
0
  }
4156
0
  smartcard_trace_write_cache_w_call(log, call);
4157
0
  return status;
4158
0
}
4159
4160
LONG smartcard_unpack_get_transmit_count_call(wStream* s, GetTransmitCount_Call* call)
4161
0
{
4162
0
  WINPR_ASSERT(call);
4163
0
  wLog* log = scard_log();
4164
4165
0
  UINT32 index = 0;
4166
0
  UINT32 pbContextNdrPtr = 0;
4167
4168
0
  LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
4169
0
                                                     &pbContextNdrPtr);
4170
0
  if (status != SCARD_S_SUCCESS)
4171
0
    return status;
4172
4173
0
  status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
4174
0
  if (status != SCARD_S_SUCCESS)
4175
0
    return status;
4176
4177
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4178
0
                                                    &(call->handles.hContext));
4179
0
  if (status != SCARD_S_SUCCESS)
4180
0
  {
4181
0
    WLog_Print(log, WLOG_ERROR,
4182
0
               "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
4183
0
               status);
4184
0
    return status;
4185
0
  }
4186
4187
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
4188
0
  if (status != SCARD_S_SUCCESS)
4189
0
    WLog_Print(log, WLOG_ERROR,
4190
0
               "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status);
4191
4192
0
  smartcard_trace_get_transmit_count_call(log, call);
4193
0
  return status;
4194
0
}
4195
4196
LONG smartcard_unpack_get_reader_icon_call(wStream* s, GetReaderIcon_Call* call)
4197
0
{
4198
0
  WINPR_ASSERT(call);
4199
0
  wLog* log = scard_log();
4200
0
  return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext,
4201
0
                                                      &call->szReaderName);
4202
0
}
4203
4204
LONG smartcard_unpack_context_and_string_a_call(wStream* s, ContextAndStringA_Call* call)
4205
0
{
4206
0
  WINPR_ASSERT(call);
4207
0
  wLog* log = scard_log();
4208
0
  return smartcard_unpack_common_context_and_string_a(log, s, &call->handles.hContext, &call->sz);
4209
0
}
4210
4211
LONG smartcard_unpack_context_and_string_w_call(wStream* s, ContextAndStringW_Call* call)
4212
0
{
4213
0
  WINPR_ASSERT(call);
4214
0
  wLog* log = scard_log();
4215
0
  return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext, &call->sz);
4216
0
}
4217
4218
LONG smartcard_unpack_get_device_type_id_call(wStream* s, GetDeviceTypeId_Call* call)
4219
0
{
4220
0
  WINPR_ASSERT(call);
4221
0
  wLog* log = scard_log();
4222
0
  return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext,
4223
0
                                                      &call->szReaderName);
4224
0
}
4225
4226
LONG smartcard_pack_device_type_id_return(wStream* s, const GetDeviceTypeId_Return* ret)
4227
0
{
4228
0
  WINPR_ASSERT(ret);
4229
0
  wLog* log = scard_log();
4230
0
  smartcard_trace_device_type_id_return(log, ret);
4231
4232
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
4233
0
  {
4234
0
    WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4235
0
    return SCARD_F_INTERNAL_ERROR;
4236
0
  }
4237
4238
0
  Stream_Write_UINT32(s, ret->dwDeviceId); /* cBytes (4 bytes) */
4239
4240
0
  return ret->ReturnCode;
4241
0
}
4242
4243
LONG smartcard_pack_locate_cards_return(wStream* s, const LocateCards_Return* ret)
4244
0
{
4245
0
  WINPR_ASSERT(ret);
4246
0
  wLog* log = scard_log();
4247
4248
0
  LONG status = 0;
4249
0
  UINT32 cbDataLen = ret->cReaders;
4250
0
  UINT32 index = 0;
4251
4252
0
  smartcard_trace_locate_cards_return(log, ret);
4253
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
4254
0
    cbDataLen = 0;
4255
0
  if (cbDataLen == SCARD_AUTOALLOCATE)
4256
0
    cbDataLen = 0;
4257
4258
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
4259
0
  {
4260
0
    WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4261
0
    return SCARD_F_INTERNAL_ERROR;
4262
0
  }
4263
4264
0
  Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
4265
0
  if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
4266
0
    return SCARD_E_NO_MEMORY;
4267
4268
0
  status = smartcard_ndr_write_state(s, ret->rgReaderStates, cbDataLen, NDR_PTR_SIMPLE);
4269
0
  if (status != SCARD_S_SUCCESS)
4270
0
    return status;
4271
0
  return ret->ReturnCode;
4272
0
}
4273
4274
LONG smartcard_pack_get_reader_icon_return(wStream* s, const GetReaderIcon_Return* ret)
4275
0
{
4276
0
  WINPR_ASSERT(ret);
4277
0
  wLog* log = scard_log();
4278
4279
0
  LONG status = 0;
4280
0
  UINT32 index = 0;
4281
0
  UINT32 cbDataLen = ret->cbDataLen;
4282
0
  smartcard_trace_get_reader_icon_return(log, ret);
4283
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
4284
0
    cbDataLen = 0;
4285
0
  if (cbDataLen == SCARD_AUTOALLOCATE)
4286
0
    cbDataLen = 0;
4287
4288
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
4289
0
  {
4290
0
    WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4291
0
    return SCARD_F_INTERNAL_ERROR;
4292
0
  }
4293
4294
0
  Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
4295
0
  if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
4296
0
    return SCARD_E_NO_MEMORY;
4297
4298
0
  status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4299
0
  if (status != SCARD_S_SUCCESS)
4300
0
    return status;
4301
0
  return ret->ReturnCode;
4302
0
}
4303
4304
LONG smartcard_pack_get_transmit_count_return(wStream* s, const GetTransmitCount_Return* ret)
4305
0
{
4306
0
  WINPR_ASSERT(ret);
4307
0
  wLog* log = scard_log();
4308
4309
0
  smartcard_trace_get_transmit_count_return(log, ret);
4310
4311
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
4312
0
  {
4313
0
    WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4314
0
    return SCARD_F_INTERNAL_ERROR;
4315
0
  }
4316
4317
0
  Stream_Write_UINT32(s, ret->cTransmitCount); /* cBytes (4 cbDataLen) */
4318
4319
0
  return ret->ReturnCode;
4320
0
}
4321
4322
LONG smartcard_pack_read_cache_return(wStream* s, const ReadCache_Return* ret)
4323
0
{
4324
0
  WINPR_ASSERT(ret);
4325
0
  wLog* log = scard_log();
4326
4327
0
  LONG status = 0;
4328
0
  UINT32 index = 0;
4329
0
  UINT32 cbDataLen = ret->cbDataLen;
4330
0
  smartcard_trace_read_cache_return(log, ret);
4331
0
  if (ret->ReturnCode != SCARD_S_SUCCESS)
4332
0
    cbDataLen = 0;
4333
4334
0
  if (cbDataLen == SCARD_AUTOALLOCATE)
4335
0
    cbDataLen = 0;
4336
4337
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
4338
0
  {
4339
0
    WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4340
0
    return SCARD_F_INTERNAL_ERROR;
4341
0
  }
4342
4343
0
  Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
4344
0
  if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
4345
0
    return SCARD_E_NO_MEMORY;
4346
4347
0
  status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4348
0
  if (status != SCARD_S_SUCCESS)
4349
0
    return status;
4350
0
  return ret->ReturnCode;
4351
0
}
4352
4353
LONG smartcard_pack_context_call(wStream* s, const Context_Call* call, const char* name)
4354
0
{
4355
0
  WINPR_ASSERT(call);
4356
0
  wLog* log = scard_log();
4357
0
  UINT32 index = 0;
4358
4359
0
  smartcard_trace_context_call(log, call, name);
4360
4361
0
  LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4362
0
  if (status != SCARD_S_SUCCESS)
4363
0
    return status;
4364
4365
0
  return smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4366
0
}
4367
4368
LONG smartcard_pack_list_readers_call(wStream* s, const ListReaders_Call* call, BOOL unicode)
4369
0
{
4370
0
  WINPR_ASSERT(call);
4371
0
  wLog* log = scard_log();
4372
0
  UINT32 index = 0;
4373
4374
0
  smartcard_trace_list_readers_call(log, call, unicode);
4375
4376
0
  LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4377
0
  if (status != SCARD_S_SUCCESS)
4378
0
    return status;
4379
4380
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
4381
0
    return SCARD_E_NO_MEMORY;
4382
4383
0
  Stream_Write_UINT32(s, call->cBytes);
4384
0
  if (!smartcard_ndr_pointer_write(s, &index, call->cBytes))
4385
0
    return SCARD_E_NO_MEMORY;
4386
4387
0
  if (!Stream_EnsureRemainingCapacity(s, 8))
4388
0
    return SCARD_E_NO_MEMORY;
4389
4390
0
  Stream_Write_INT32(s, call->fmszReadersIsNULL);
4391
0
  Stream_Write_UINT32(s, call->cchReaders);
4392
4393
0
  status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4394
0
  if (status != SCARD_S_SUCCESS)
4395
0
    return status;
4396
4397
0
  if (call->cBytes > 0)
4398
0
  {
4399
0
    status = smartcard_ndr_write(s, call->mszGroups, call->cBytes, 1, NDR_PTR_SIMPLE);
4400
0
    if (status != SCARD_S_SUCCESS)
4401
0
      return status;
4402
0
  }
4403
4404
0
  return SCARD_S_SUCCESS;
4405
0
}
4406
4407
static LONG smartcard_pack_reader_state_a(wStream* s, const LPSCARD_READERSTATEA rgReaderStates,
4408
                                          UINT32 cReaders, UINT32* ptrIndex)
4409
0
{
4410
0
  WINPR_ASSERT(rgReaderStates || (cReaders == 0));
4411
4412
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
4413
0
    return SCARD_E_NO_MEMORY;
4414
4415
0
  Stream_Write_UINT32(s, cReaders);
4416
4417
0
  for (UINT32 i = 0; i < cReaders; i++)
4418
0
  {
4419
0
    const SCARD_READERSTATEA* state = &rgReaderStates[i];
4420
4421
0
    if (!Stream_EnsureRemainingCapacity(s, 52))
4422
0
      return SCARD_E_NO_MEMORY;
4423
4424
0
    const UINT32 nameLen = state->szReader ? (UINT32)(strlen(state->szReader) + 1) : 0;
4425
0
    if (!smartcard_ndr_pointer_write(s, ptrIndex, nameLen))
4426
0
      return SCARD_E_NO_MEMORY;
4427
4428
0
    Stream_Write_UINT32(s, state->dwCurrentState);
4429
0
    Stream_Write_UINT32(s, state->dwEventState);
4430
0
    Stream_Write_UINT32(s, state->cbAtr);
4431
0
    Stream_Write(s, state->rgbAtr, 36);
4432
0
  }
4433
4434
0
  for (UINT32 i = 0; i < cReaders; i++)
4435
0
  {
4436
0
    const SCARD_READERSTATEA* state = &rgReaderStates[i];
4437
4438
0
    if (state->szReader)
4439
0
    {
4440
0
      const UINT32 nameLen = (UINT32)(strlen(state->szReader) + 1);
4441
0
      LONG status = smartcard_ndr_write_a(s, state->szReader, nameLen, NDR_PTR_FULL);
4442
0
      if (status != SCARD_S_SUCCESS)
4443
0
        return status;
4444
0
    }
4445
0
  }
4446
4447
0
  return SCARD_S_SUCCESS;
4448
0
}
4449
4450
static LONG smartcard_pack_reader_state_w(wStream* s, const LPSCARD_READERSTATEW rgReaderStates,
4451
                                          UINT32 cReaders, UINT32* ptrIndex)
4452
0
{
4453
0
  WINPR_ASSERT(rgReaderStates || (cReaders == 0));
4454
4455
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
4456
0
    return SCARD_E_NO_MEMORY;
4457
4458
0
  Stream_Write_UINT32(s, cReaders);
4459
4460
0
  for (UINT32 i = 0; i < cReaders; i++)
4461
0
  {
4462
0
    const SCARD_READERSTATEW* state = &rgReaderStates[i];
4463
4464
0
    if (!Stream_EnsureRemainingCapacity(s, 52))
4465
0
      return SCARD_E_NO_MEMORY;
4466
4467
0
    const UINT32 nameLen = state->szReader ? (UINT32)(_wcslen(state->szReader) + 1) : 0;
4468
0
    if (!smartcard_ndr_pointer_write(s, ptrIndex, nameLen))
4469
0
      return SCARD_E_NO_MEMORY;
4470
4471
0
    Stream_Write_UINT32(s, state->dwCurrentState);
4472
0
    Stream_Write_UINT32(s, state->dwEventState);
4473
0
    Stream_Write_UINT32(s, state->cbAtr);
4474
0
    Stream_Write(s, state->rgbAtr, 36);
4475
0
  }
4476
4477
0
  for (UINT32 i = 0; i < cReaders; i++)
4478
0
  {
4479
0
    const SCARD_READERSTATEW* state = &rgReaderStates[i];
4480
4481
0
    if (state->szReader)
4482
0
    {
4483
0
      const UINT32 nameLen = (UINT32)(_wcslen(state->szReader) + 1);
4484
0
      LONG status = smartcard_ndr_write_w(s, state->szReader, nameLen, NDR_PTR_FULL);
4485
0
      if (status != SCARD_S_SUCCESS)
4486
0
        return status;
4487
0
    }
4488
0
  }
4489
4490
0
  return SCARD_S_SUCCESS;
4491
0
}
4492
4493
LONG smartcard_pack_get_status_change_a_call(wStream* s, const GetStatusChangeA_Call* call)
4494
0
{
4495
0
  WINPR_ASSERT(call);
4496
0
  wLog* log = scard_log();
4497
0
  UINT32 index = 0;
4498
4499
0
  smartcard_trace_get_status_change_a_call(log, call);
4500
4501
0
  LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4502
0
  if (status != SCARD_S_SUCCESS)
4503
0
    return status;
4504
4505
0
  if (!Stream_EnsureRemainingCapacity(s, 8))
4506
0
    return SCARD_E_NO_MEMORY;
4507
4508
0
  Stream_Write_UINT32(s, call->dwTimeOut);
4509
0
  Stream_Write_UINT32(s, call->cReaders);
4510
4511
0
  if (!smartcard_ndr_pointer_write(s, &index, call->cReaders))
4512
0
    return SCARD_E_NO_MEMORY;
4513
4514
0
  status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4515
0
  if (status != SCARD_S_SUCCESS)
4516
0
    return status;
4517
4518
0
  if (call->cReaders > 0)
4519
0
  {
4520
0
    status = smartcard_pack_reader_state_a(s, call->rgReaderStates, call->cReaders, &index);
4521
0
    if (status != SCARD_S_SUCCESS)
4522
0
      return status;
4523
0
  }
4524
4525
0
  return SCARD_S_SUCCESS;
4526
0
}
4527
4528
LONG smartcard_pack_get_status_change_w_call(wStream* s, const GetStatusChangeW_Call* call)
4529
0
{
4530
0
  WINPR_ASSERT(call);
4531
0
  wLog* log = scard_log();
4532
0
  UINT32 index = 0;
4533
4534
0
  smartcard_trace_get_status_change_w_call(log, call);
4535
4536
0
  LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4537
0
  if (status != SCARD_S_SUCCESS)
4538
0
    return status;
4539
4540
0
  if (!Stream_EnsureRemainingCapacity(s, 8))
4541
0
    return SCARD_E_NO_MEMORY;
4542
4543
0
  Stream_Write_UINT32(s, call->dwTimeOut);
4544
0
  Stream_Write_UINT32(s, call->cReaders);
4545
4546
0
  if (!smartcard_ndr_pointer_write(s, &index, call->cReaders))
4547
0
    return SCARD_E_NO_MEMORY;
4548
4549
0
  status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4550
0
  if (status != SCARD_S_SUCCESS)
4551
0
    return status;
4552
4553
0
  if (call->cReaders > 0)
4554
0
  {
4555
0
    status = smartcard_pack_reader_state_w(s, call->rgReaderStates, call->cReaders, &index);
4556
0
    if (status != SCARD_S_SUCCESS)
4557
0
      return status;
4558
0
  }
4559
4560
0
  return SCARD_S_SUCCESS;
4561
0
}
4562
4563
LONG smartcard_pack_connect_a_call(wStream* s, const ConnectA_Call* call)
4564
0
{
4565
0
  WINPR_ASSERT(call);
4566
0
  wLog* log = scard_log();
4567
0
  UINT32 index = 0;
4568
4569
0
  smartcard_trace_connect_a_call(log, call);
4570
4571
0
  const UINT32 readerLen = call->szReader ? (UINT32)(strlen(call->szReader) + 1) : 0;
4572
0
  if (!smartcard_ndr_pointer_write(s, &index, readerLen))
4573
0
    return SCARD_E_NO_MEMORY;
4574
4575
0
  LONG status =
4576
0
      smartcard_pack_redir_scard_context(log, s, &call->Common.handles.hContext, &index);
4577
0
  if (status != SCARD_S_SUCCESS)
4578
0
    return status;
4579
4580
0
  if (!Stream_EnsureRemainingCapacity(s, 8))
4581
0
    return SCARD_E_NO_MEMORY;
4582
4583
0
  Stream_Write_UINT32(s, call->Common.dwShareMode);
4584
0
  Stream_Write_UINT32(s, call->Common.dwPreferredProtocols);
4585
4586
0
  if (call->szReader)
4587
0
  {
4588
0
    status = smartcard_ndr_write_a(s, call->szReader, readerLen, NDR_PTR_FULL);
4589
0
    if (status != SCARD_S_SUCCESS)
4590
0
      return status;
4591
0
  }
4592
4593
0
  return smartcard_pack_redir_scard_context_ref(log, s, &call->Common.handles.hContext);
4594
0
}
4595
4596
LONG smartcard_pack_connect_w_call(wStream* s, const ConnectW_Call* call)
4597
0
{
4598
0
  WINPR_ASSERT(call);
4599
0
  wLog* log = scard_log();
4600
0
  UINT32 index = 0;
4601
4602
0
  smartcard_trace_connect_w_call(log, call);
4603
4604
0
  const UINT32 readerLen = call->szReader ? (UINT32)(_wcslen(call->szReader) + 1) : 0;
4605
0
  if (!smartcard_ndr_pointer_write(s, &index, readerLen))
4606
0
    return SCARD_E_NO_MEMORY;
4607
4608
0
  LONG status =
4609
0
      smartcard_pack_redir_scard_context(log, s, &call->Common.handles.hContext, &index);
4610
0
  if (status != SCARD_S_SUCCESS)
4611
0
    return status;
4612
4613
0
  if (!Stream_EnsureRemainingCapacity(s, 8))
4614
0
    return SCARD_E_NO_MEMORY;
4615
4616
0
  Stream_Write_UINT32(s, call->Common.dwShareMode);
4617
0
  Stream_Write_UINT32(s, call->Common.dwPreferredProtocols);
4618
4619
0
  if (call->szReader)
4620
0
  {
4621
0
    status = smartcard_ndr_write_w(s, call->szReader, readerLen, NDR_PTR_FULL);
4622
0
    if (status != SCARD_S_SUCCESS)
4623
0
      return status;
4624
0
  }
4625
4626
0
  return smartcard_pack_redir_scard_context_ref(log, s, &call->Common.handles.hContext);
4627
0
}
4628
4629
LONG smartcard_pack_control_call(wStream* s, const Control_Call* call)
4630
0
{
4631
0
  WINPR_ASSERT(call);
4632
0
  wLog* log = scard_log();
4633
0
  UINT32 index = 0;
4634
4635
0
  smartcard_trace_control_call(log, call);
4636
4637
0
  LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4638
0
  if (status != SCARD_S_SUCCESS)
4639
0
    return status;
4640
4641
0
  status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4642
0
  if (status != SCARD_S_SUCCESS)
4643
0
    return status;
4644
4645
0
  if (!Stream_EnsureRemainingCapacity(s, 8))
4646
0
    return SCARD_E_NO_MEMORY;
4647
4648
0
  Stream_Write_UINT32(s, call->dwControlCode);
4649
0
  Stream_Write_UINT32(s, call->cbInBufferSize);
4650
0
  if (!smartcard_ndr_pointer_write(s, &index, call->cbInBufferSize))
4651
0
    return SCARD_E_NO_MEMORY;
4652
4653
0
  Stream_Write_INT32(s, call->fpvOutBufferIsNULL);
4654
0
  Stream_Write_UINT32(s, call->cbOutBufferSize);
4655
4656
0
  status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4657
0
  if (status != SCARD_S_SUCCESS)
4658
0
    return status;
4659
4660
0
  status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4661
0
  if (status != SCARD_S_SUCCESS)
4662
0
    return status;
4663
4664
0
  if (call->cbInBufferSize)
4665
0
  {
4666
0
    status = smartcard_ndr_write(s, call->pvInBuffer, call->cbInBufferSize, 1, NDR_PTR_SIMPLE);
4667
0
    if (status != SCARD_S_SUCCESS)
4668
0
      return status;
4669
0
  }
4670
4671
0
  return status;
4672
0
}
4673
4674
LONG smartcard_pack_hcard_and_disposition_call(wStream* s, const HCardAndDisposition_Call* call,
4675
                                               const char* name)
4676
0
{
4677
0
  WINPR_ASSERT(call);
4678
0
  wLog* log = scard_log();
4679
0
  UINT32 index = 0;
4680
4681
0
  smartcard_trace_hcard_and_disposition_call(log, call, name);
4682
4683
0
  LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4684
0
  if (status != SCARD_S_SUCCESS)
4685
0
    return status;
4686
4687
0
  status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4688
0
  if (status != SCARD_S_SUCCESS)
4689
0
    return status;
4690
4691
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
4692
0
    return SCARD_E_NO_MEMORY;
4693
4694
0
  Stream_Write_UINT32(s, call->dwDisposition);
4695
4696
0
  status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4697
0
  if (status != SCARD_S_SUCCESS)
4698
0
    return status;
4699
4700
0
  return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4701
0
}
4702
4703
LONG smartcard_pack_transmit_call(wStream* s, const Transmit_Call* call)
4704
0
{
4705
0
  WINPR_ASSERT(call);
4706
0
  wLog* log = scard_log();
4707
0
  UINT32 index = 0;
4708
4709
0
  smartcard_trace_transmit_call(log, call);
4710
4711
0
  LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4712
0
  if (status != SCARD_S_SUCCESS)
4713
0
    return status;
4714
4715
0
  status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4716
0
  if (status != SCARD_S_SUCCESS)
4717
0
    return status;
4718
4719
0
  UINT32 cbExtraBytes = 0;
4720
0
  const BYTE* pbExtraBytes = nullptr;
4721
0
  if (call->pioSendPci)
4722
0
  {
4723
0
    cbExtraBytes = (UINT32)(call->pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
4724
0
    if (cbExtraBytes > 0)
4725
0
      pbExtraBytes = &((const BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
4726
0
  }
4727
4728
0
  if (!Stream_EnsureRemainingCapacity(s, 32))
4729
0
    return SCARD_E_NO_MEMORY;
4730
4731
0
  Stream_Write_UINT32(s, call->pioSendPci ? call->pioSendPci->dwProtocol : 0);
4732
0
  Stream_Write_UINT32(s, cbExtraBytes);
4733
0
  if (!smartcard_ndr_pointer_write(s, &index, cbExtraBytes))
4734
0
    return SCARD_E_NO_MEMORY;
4735
4736
0
  Stream_Write_UINT32(s, call->cbSendLength);
4737
0
  if (!smartcard_ndr_pointer_write(s, &index, call->cbSendLength))
4738
0
    return SCARD_E_NO_MEMORY;
4739
4740
0
  const UINT32 recvPciLen = call->pioRecvPci ? (UINT32)call->pioRecvPci->cbPciLength : 0;
4741
0
  if (!smartcard_ndr_pointer_write(s, &index, recvPciLen))
4742
0
    return SCARD_E_NO_MEMORY;
4743
4744
0
  Stream_Write_INT32(s, call->fpbRecvBufferIsNULL);
4745
0
  Stream_Write_UINT32(s, call->cbRecvLength);
4746
4747
0
  status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4748
0
  if (status != SCARD_S_SUCCESS)
4749
0
    return status;
4750
4751
0
  status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4752
0
  if (status != SCARD_S_SUCCESS)
4753
0
    return status;
4754
4755
0
  if (cbExtraBytes > 0)
4756
0
  {
4757
0
    status = smartcard_ndr_write(s, pbExtraBytes, cbExtraBytes, 1, NDR_PTR_SIMPLE);
4758
0
    if (status != SCARD_S_SUCCESS)
4759
0
      return status;
4760
0
  }
4761
4762
0
  if (call->cbSendLength > 0)
4763
0
  {
4764
0
    status = smartcard_ndr_write(s, call->pbSendBuffer, call->cbSendLength, 1, NDR_PTR_SIMPLE);
4765
0
    if (status != SCARD_S_SUCCESS)
4766
0
      return status;
4767
0
  }
4768
4769
0
  if (call->pioRecvPci && recvPciLen > 0)
4770
0
  {
4771
0
    UINT32 cbRecvExtra = (UINT32)(call->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
4772
0
    const BYTE* pbRecvExtra = &((const BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
4773
4774
0
    if (!Stream_EnsureRemainingCapacity(s, 12))
4775
0
      return SCARD_E_NO_MEMORY;
4776
4777
0
    Stream_Write_UINT32(s, call->pioRecvPci->dwProtocol);
4778
0
    Stream_Write_UINT32(s, cbRecvExtra);
4779
0
    if (!smartcard_ndr_pointer_write(s, &index, cbRecvExtra))
4780
0
      return SCARD_E_NO_MEMORY;
4781
4782
0
    if (cbRecvExtra > 0)
4783
0
    {
4784
0
      status = smartcard_ndr_write(s, pbRecvExtra, cbRecvExtra, 1, NDR_PTR_SIMPLE);
4785
0
      if (status != SCARD_S_SUCCESS)
4786
0
        return status;
4787
0
    }
4788
0
  }
4789
4790
0
  return SCARD_S_SUCCESS;
4791
0
}
4792
4793
LONG smartcard_pack_get_attrib_call(wStream* s, const GetAttrib_Call* call)
4794
0
{
4795
0
  WINPR_ASSERT(call);
4796
0
  wLog* log = scard_log();
4797
0
  UINT32 index = 0;
4798
4799
0
  smartcard_trace_get_attrib_call(log, call);
4800
4801
0
  LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4802
0
  if (status != SCARD_S_SUCCESS)
4803
0
    return status;
4804
4805
0
  status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4806
0
  if (status != SCARD_S_SUCCESS)
4807
0
    return status;
4808
4809
0
  if (!Stream_EnsureRemainingCapacity(s, 12))
4810
0
    return STATUS_NO_MEMORY;
4811
4812
0
  Stream_Write_UINT32(s, call->dwAttrId);
4813
0
  Stream_Write_INT32(s, call->fpbAttrIsNULL);
4814
0
  Stream_Write_UINT32(s, call->cbAttrLen);
4815
4816
0
  status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4817
0
  if (status != SCARD_S_SUCCESS)
4818
0
    return status;
4819
4820
0
  return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4821
0
}
4822
4823
LONG smartcard_unpack_list_readers_return(wStream* s, ListReaders_Return* ret, BOOL unicode)
4824
0
{
4825
0
  WINPR_ASSERT(ret);
4826
0
  wLog* log = scard_log();
4827
0
  UINT32 index = 0;
4828
0
  UINT32 mszNdrPtr = 0;
4829
4830
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4831
0
    return STATUS_BUFFER_TOO_SMALL;
4832
4833
0
  const UINT32 cBytes = Stream_Get_UINT32(s);
4834
4835
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
4836
0
    return ERROR_INVALID_DATA;
4837
4838
0
  if (mszNdrPtr)
4839
0
  {
4840
0
    LONG status = smartcard_ndr_read(log, s, &ret->msz, cBytes, 1, NDR_PTR_SIMPLE);
4841
0
    if (status != SCARD_S_SUCCESS)
4842
0
      return status;
4843
0
    ret->cBytes = cBytes;
4844
0
  }
4845
4846
0
  smartcard_trace_list_readers_return(log, ret, unicode);
4847
0
  return SCARD_S_SUCCESS;
4848
0
}
4849
4850
LONG smartcard_unpack_get_status_change_return(wStream* s, GetStatusChange_Return* ret,
4851
                                               BOOL unicode)
4852
0
{
4853
0
  WINPR_ASSERT(ret);
4854
0
  wLog* log = scard_log();
4855
0
  UINT32 index = 0;
4856
0
  UINT32 ndrPtr = 0;
4857
4858
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4859
0
    return STATUS_BUFFER_TOO_SMALL;
4860
4861
0
  Stream_Read_UINT32(s, ret->cReaders);
4862
4863
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
4864
0
    return ERROR_INVALID_DATA;
4865
4866
0
  if (ndrPtr && ret->cReaders > 0)
4867
0
  {
4868
0
    LONG status =
4869
0
        smartcard_ndr_read_state(log, s, &ret->rgReaderStates, ret->cReaders, NDR_PTR_SIMPLE);
4870
0
    if (status != SCARD_S_SUCCESS)
4871
0
      return status;
4872
0
  }
4873
0
  else
4874
0
    ret->rgReaderStates = nullptr;
4875
4876
0
  smartcard_trace_get_status_change_return(log, ret, unicode);
4877
0
  return SCARD_S_SUCCESS;
4878
0
}
4879
4880
LONG smartcard_unpack_connect_return(wStream* s, Connect_Return* ret)
4881
0
{
4882
0
  WINPR_ASSERT(ret);
4883
0
  wLog* log = scard_log();
4884
0
  UINT32 index = 0;
4885
0
  UINT32 pbContextNdrPtr = 0;
4886
4887
0
  LONG status =
4888
0
      smartcard_unpack_redir_scard_context(log, s, &ret->hContext, &index, &pbContextNdrPtr);
4889
0
  if (status != SCARD_S_SUCCESS)
4890
0
    return status;
4891
4892
0
  status = smartcard_unpack_redir_scard_handle(log, s, &ret->hCard, &index);
4893
0
  if (status != SCARD_S_SUCCESS)
4894
0
    return status;
4895
4896
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4897
0
    return STATUS_BUFFER_TOO_SMALL;
4898
4899
0
  Stream_Read_UINT32(s, ret->dwActiveProtocol);
4900
4901
0
  status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &ret->hContext);
4902
0
  if (status != SCARD_S_SUCCESS)
4903
0
    return status;
4904
4905
0
  status = smartcard_unpack_redir_scard_handle_ref(log, s, &ret->hCard);
4906
0
  if (status != SCARD_S_SUCCESS)
4907
0
    return status;
4908
4909
0
  smartcard_trace_connect_return(log, ret);
4910
0
  return SCARD_S_SUCCESS;
4911
0
}
4912
4913
LONG smartcard_unpack_control_return(wStream* s, Control_Return* ret)
4914
0
{
4915
0
  WINPR_ASSERT(ret);
4916
0
  wLog* log = scard_log();
4917
0
  UINT32 index = 0;
4918
0
  UINT32 pvOutBufferNdrPtr = 0;
4919
4920
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
4921
0
    return STATUS_BUFFER_TOO_SMALL;
4922
4923
0
  const UINT32 cbOutBufferSize = Stream_Get_UINT32(s);
4924
4925
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &pvOutBufferNdrPtr))
4926
0
    return ERROR_INVALID_DATA;
4927
4928
0
  if (pvOutBufferNdrPtr && (cbOutBufferSize > 0))
4929
0
  {
4930
0
    LONG status =
4931
0
        smartcard_ndr_read(log, s, &ret->pvOutBuffer, cbOutBufferSize, 1, NDR_PTR_SIMPLE);
4932
0
    if (status != SCARD_S_SUCCESS)
4933
0
      return status;
4934
0
    ret->cbOutBufferSize = cbOutBufferSize;
4935
0
  }
4936
0
  smartcard_trace_control_return(log, ret);
4937
0
  return SCARD_S_SUCCESS;
4938
0
}
4939
4940
LONG smartcard_unpack_transmit_return(wStream* s, Transmit_Return* ret)
4941
0
{
4942
0
  WINPR_ASSERT(ret);
4943
0
  wLog* log = scard_log();
4944
0
  UINT32 index = 0;
4945
0
  UINT32 recvPciNdrPtr = 0;
4946
0
  UINT32 recvBufferNdrPtr = 0;
4947
4948
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &recvPciNdrPtr))
4949
0
    return ERROR_INVALID_DATA;
4950
4951
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4952
0
    return STATUS_BUFFER_TOO_SMALL;
4953
4954
0
  const UINT32 cbRecvLength = Stream_Get_UINT32(s);
4955
4956
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &recvBufferNdrPtr))
4957
0
    return ERROR_INVALID_DATA;
4958
4959
0
  if (recvPciNdrPtr)
4960
0
  {
4961
0
    if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
4962
0
      return STATUS_BUFFER_TOO_SMALL;
4963
4964
0
    UINT32 dwProtocol = 0;
4965
0
    UINT32 cbExtraBytes = 0;
4966
0
    Stream_Read_UINT32(s, dwProtocol);
4967
0
    Stream_Read_UINT32(s, cbExtraBytes);
4968
4969
0
    UINT32 pbExtraBytesNdrPtr = 0;
4970
0
    if (!smartcard_ndr_pointer_read(log, s, &index, &pbExtraBytesNdrPtr))
4971
0
      return ERROR_INVALID_DATA;
4972
4973
0
    if (pbExtraBytesNdrPtr)
4974
0
    {
4975
0
      if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4976
0
        return STATUS_BUFFER_TOO_SMALL;
4977
4978
0
      UINT32 length = 0;
4979
0
      Stream_Read_UINT32(s, length);
4980
0
      if (length != cbExtraBytes)
4981
0
      {
4982
0
        WLog_Print(log, WLOG_WARN,
4983
0
                   "Transmit_Return unexpected length: Actual: %" PRIu32
4984
0
                   ", Expected: %" PRIu32 " (pioRecvPci.cbExtraBytes)",
4985
0
                   length, cbExtraBytes);
4986
0
        return STATUS_INVALID_PARAMETER;
4987
0
      }
4988
4989
0
      if (!Stream_CheckAndLogRequiredLengthWLog(log, s, cbExtraBytes))
4990
0
        return STATUS_BUFFER_TOO_SMALL;
4991
4992
0
      ret->pioRecvPci = (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + cbExtraBytes);
4993
0
      if (!ret->pioRecvPci)
4994
0
        return SCARD_E_NO_MEMORY;
4995
4996
0
      ret->pioRecvPci->dwProtocol = dwProtocol;
4997
0
      ret->pioRecvPci->cbPciLength = (DWORD)(sizeof(SCARD_IO_REQUEST) + cbExtraBytes);
4998
4999
0
      BYTE* pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
5000
0
      Stream_Read(s, pbExtraBytes, length);
5001
0
      if (smartcard_unpack_read_size_align(s, cbExtraBytes, 4) < 0)
5002
0
        return STATUS_INVALID_PARAMETER;
5003
0
    }
5004
0
    else
5005
0
    {
5006
0
      ret->pioRecvPci = (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST));
5007
0
      if (!ret->pioRecvPci)
5008
0
        return SCARD_E_NO_MEMORY;
5009
5010
0
      ret->pioRecvPci->dwProtocol = dwProtocol;
5011
0
      ret->pioRecvPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
5012
0
    }
5013
0
  }
5014
5015
0
  if (recvBufferNdrPtr && (cbRecvLength > 0))
5016
0
  {
5017
0
    LONG status =
5018
0
        smartcard_ndr_read(log, s, &ret->pbRecvBuffer, cbRecvLength, 1, NDR_PTR_SIMPLE);
5019
0
    if (status != SCARD_S_SUCCESS)
5020
0
      return status;
5021
0
    ret->cbRecvLength = cbRecvLength;
5022
0
  }
5023
5024
0
  smartcard_trace_transmit_return(log, ret);
5025
0
  return SCARD_S_SUCCESS;
5026
0
}
5027
5028
LONG smartcard_unpack_get_attrib_return(wStream* s, GetAttrib_Return* ret)
5029
0
{
5030
0
  WINPR_ASSERT(ret);
5031
0
  wLog* log = scard_log();
5032
0
  UINT32 index = 0;
5033
0
  UINT32 pbAttrPtr = 0;
5034
5035
0
  if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
5036
0
    return STATUS_BUFFER_TOO_SMALL;
5037
5038
0
  const UINT32 cbAttrLen = Stream_Get_UINT32(s);
5039
5040
0
  if (!smartcard_ndr_pointer_read(log, s, &index, &pbAttrPtr))
5041
0
    return ERROR_INVALID_DATA;
5042
5043
0
  LONG status = smartcard_ndr_read(log, s, &ret->pbAttr, cbAttrLen, 1, NDR_PTR_SIMPLE);
5044
0
  if (status != SCARD_S_SUCCESS)
5045
0
    return status;
5046
0
  ret->cbAttrLen = cbAttrLen;
5047
5048
0
  smartcard_trace_get_attrib_return(log, ret, 0);
5049
0
  return SCARD_S_SUCCESS;
5050
0
}
5051
5052
BOOL smartcard_reader_state_return_is_valid_ex(size_t pos, const ReaderState_Return* val,
5053
                                               const char* file, size_t line, const char* fkt)
5054
0
{
5055
0
  if (!val)
5056
0
  {
5057
0
    WLog_Print_dbg_tag(SCARD_TAG, WLOG_WARN, line, file, fkt, "[%" PRIuz "] val = nullptr",
5058
0
                       pos);
5059
0
    return FALSE;
5060
0
  }
5061
0
  if (val->cbAtr > sizeof(val->rgbAtr))
5062
0
  {
5063
0
    WLog_Print_dbg_tag(SCARD_TAG, WLOG_WARN, line, file, fkt,
5064
0
                       "[%" PRIuz "] val->cbAtr=%" PRIu32 ", max=%" PRIuz, pos, val->cbAtr,
5065
0
                       sizeof(val->rgbAtr));
5066
0
    return FALSE;
5067
0
  }
5068
5069
0
  return TRUE;
5070
0
}