Coverage Report

Created: 2026-01-16 07:10

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