Coverage Report

Created: 2026-10-15 06:31

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