Coverage Report

Created: 2026-09-14 06:32

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