Coverage Report

Created: 2026-10-28 06:49

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