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