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,
1684  WINPR_ASSERTING_INT_CAST(size_t, line)))
1685  return ERROR_INVALID_DATA;
1686 
1687  if (((context->cbContext == 0) && pbContextNdrPtr) ||
1688  ((context->cbContext != 0) && !pbContextNdrPtr))
1689  {
1690  WLog_WARN(TAG,
1691  "REDIR_SCARDCONTEXT cbContext (%" PRIu32 ") pbContextNdrPtr (%" PRIu32
1692  ") inconsistency",
1693  context->cbContext, pbContextNdrPtr);
1694  return STATUS_INVALID_PARAMETER;
1695  }
1696 
1697  if (!Stream_CheckAndLogRequiredLength(TAG, s, context->cbContext))
1698  return STATUS_INVALID_PARAMETER;
1699 
1700  *ppbContextNdrPtr = pbContextNdrPtr;
1701  return SCARD_S_SUCCESS;
1702 }
1703 
1704 LONG smartcard_pack_redir_scard_context(wStream* s, const REDIR_SCARDCONTEXT* context, DWORD* index)
1705 {
1706  const UINT32 pbContextNdrPtr = 0x00020000 + *index * 4;
1707 
1708  if (context->cbContext != 0)
1709  {
1710  Stream_Write_UINT32(s, context->cbContext); /* cbContext (4 bytes) */
1711  Stream_Write_UINT32(s, pbContextNdrPtr); /* pbContextNdrPtr (4 bytes) */
1712  *index = *index + 1;
1713  }
1714  else
1715  Stream_Zero(s, 8);
1716 
1717  return SCARD_S_SUCCESS;
1718 }
1719 
1720 LONG smartcard_unpack_redir_scard_context_ref(wStream* s, UINT32 pbContextNdrPtr,
1721  REDIR_SCARDCONTEXT* context)
1722 {
1723  UINT32 length = 0;
1724 
1725  WINPR_ASSERT(context);
1726  if (context->cbContext == 0)
1727  return SCARD_S_SUCCESS;
1728 
1729  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1730  return STATUS_BUFFER_TOO_SMALL;
1731 
1732  Stream_Read_UINT32(s, length); /* Length (4 bytes) */
1733 
1734  if (length != context->cbContext)
1735  {
1736  WLog_WARN(TAG, "REDIR_SCARDCONTEXT length (%" PRIu32 ") cbContext (%" PRIu32 ") mismatch",
1737  length, context->cbContext);
1738  return STATUS_INVALID_PARAMETER;
1739  }
1740 
1741  if ((context->cbContext != 0) && (context->cbContext != 4) && (context->cbContext != 8))
1742  {
1743  WLog_WARN(TAG, "REDIR_SCARDCONTEXT length is not 4 or 8: %" PRIu32 "", context->cbContext);
1744  return STATUS_INVALID_PARAMETER;
1745  }
1746 
1747  if (!Stream_CheckAndLogRequiredLength(TAG, s, context->cbContext))
1748  return STATUS_BUFFER_TOO_SMALL;
1749 
1750  if (context->cbContext)
1751  Stream_Read(s, &(context->pbContext), context->cbContext);
1752  else
1753  ZeroMemory(&(context->pbContext), sizeof(context->pbContext));
1754 
1755  return SCARD_S_SUCCESS;
1756 }
1757 
1758 LONG smartcard_pack_redir_scard_context_ref(wStream* s, const REDIR_SCARDCONTEXT* context)
1759 {
1760 
1761  Stream_Write_UINT32(s, context->cbContext); /* Length (4 bytes) */
1762 
1763  if (context->cbContext)
1764  {
1765  Stream_Write(s, &(context->pbContext), context->cbContext);
1766  }
1767 
1768  return SCARD_S_SUCCESS;
1769 }
1770 
1771 LONG smartcard_unpack_redir_scard_handle_(wStream* s, REDIR_SCARDHANDLE* handle, UINT32* index,
1772  const char* file, const char* function, int line)
1773 {
1774  WINPR_ASSERT(handle);
1775  ZeroMemory(handle, sizeof(REDIR_SCARDHANDLE));
1776 
1777  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1778  return STATUS_BUFFER_TOO_SMALL;
1779 
1780  Stream_Read_UINT32(s, handle->cbHandle); /* Length (4 bytes) */
1781 
1782  if (!Stream_CheckAndLogRequiredLength(TAG, s, handle->cbHandle))
1783  return STATUS_BUFFER_TOO_SMALL;
1784 
1785  if (!smartcard_ndr_pointer_read_(s, index, NULL, file, function,
1786  WINPR_ASSERTING_INT_CAST(size_t, line)))
1787  return ERROR_INVALID_DATA;
1788 
1789  return SCARD_S_SUCCESS;
1790 }
1791 
1792 LONG smartcard_pack_redir_scard_handle(wStream* s, const REDIR_SCARDHANDLE* handle, DWORD* index)
1793 {
1794  const UINT32 pbContextNdrPtr = 0x00020000 + *index * 4;
1795 
1796  if (handle->cbHandle != 0)
1797  {
1798  Stream_Write_UINT32(s, handle->cbHandle); /* cbContext (4 bytes) */
1799  Stream_Write_UINT32(s, pbContextNdrPtr); /* pbContextNdrPtr (4 bytes) */
1800  *index = *index + 1;
1801  }
1802  else
1803  Stream_Zero(s, 8);
1804  return SCARD_S_SUCCESS;
1805 }
1806 
1807 LONG smartcard_unpack_redir_scard_handle_ref(wStream* s, REDIR_SCARDHANDLE* handle)
1808 {
1809  UINT32 length = 0;
1810 
1811  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1812  return STATUS_BUFFER_TOO_SMALL;
1813 
1814  Stream_Read_UINT32(s, length); /* Length (4 bytes) */
1815 
1816  if (length != handle->cbHandle)
1817  {
1818  WLog_WARN(TAG, "REDIR_SCARDHANDLE length (%" PRIu32 ") cbHandle (%" PRIu32 ") mismatch",
1819  length, handle->cbHandle);
1820  return STATUS_INVALID_PARAMETER;
1821  }
1822 
1823  if ((handle->cbHandle != 4) && (handle->cbHandle != 8))
1824  {
1825  WLog_WARN(TAG, "REDIR_SCARDHANDLE length is not 4 or 8: %" PRIu32 "", handle->cbHandle);
1826  return STATUS_INVALID_PARAMETER;
1827  }
1828 
1829  if (!Stream_CheckAndLogRequiredLength(TAG, s, handle->cbHandle))
1830  return STATUS_BUFFER_TOO_SMALL;
1831 
1832  if (handle->cbHandle)
1833  Stream_Read(s, &(handle->pbHandle), handle->cbHandle);
1834 
1835  return SCARD_S_SUCCESS;
1836 }
1837 
1838 LONG smartcard_pack_redir_scard_handle_ref(wStream* s, const REDIR_SCARDHANDLE* handle)
1839 {
1840 
1841  Stream_Write_UINT32(s, handle->cbHandle); /* Length (4 bytes) */
1842 
1843  if (handle->cbHandle)
1844  Stream_Write(s, &(handle->pbHandle), handle->cbHandle);
1845 
1846  return SCARD_S_SUCCESS;
1847 }
1848 
1849 LONG smartcard_unpack_establish_context_call(wStream* s, EstablishContext_Call* call)
1850 {
1851  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1852  return STATUS_BUFFER_TOO_SMALL;
1853 
1854  Stream_Read_UINT32(s, call->dwScope); /* dwScope (4 bytes) */
1855  smartcard_trace_establish_context_call(call);
1856  return SCARD_S_SUCCESS;
1857 }
1858 
1859 LONG smartcard_pack_establish_context_return(wStream* s, const EstablishContext_Return* ret)
1860 {
1861  LONG status = 0;
1862  DWORD index = 0;
1863 
1864  smartcard_trace_establish_context_return(ret);
1865  if (ret->ReturnCode != SCARD_S_SUCCESS)
1866  return ret->ReturnCode;
1867 
1868  if ((status = smartcard_pack_redir_scard_context(s, &(ret->hContext), &index)))
1869  return status;
1870 
1871  return smartcard_pack_redir_scard_context_ref(s, &(ret->hContext));
1872 }
1873 
1874 LONG smartcard_unpack_context_call(wStream* s, Context_Call* call, const char* name)
1875 {
1876  UINT32 index = 0;
1877  UINT32 pbContextNdrPtr = 0;
1878 
1879  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
1880  &pbContextNdrPtr);
1881  if (status != SCARD_S_SUCCESS)
1882  return status;
1883 
1884  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
1885  &(call->handles.hContext))))
1886  WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
1887  status);
1888 
1889  smartcard_trace_context_call(call, name);
1890  return status;
1891 }
1892 
1893 LONG smartcard_unpack_list_reader_groups_call(wStream* s, ListReaderGroups_Call* call, BOOL unicode)
1894 {
1895  UINT32 index = 0;
1896  UINT32 pbContextNdrPtr = 0;
1897 
1898  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
1899  &pbContextNdrPtr);
1900 
1901  if (status != SCARD_S_SUCCESS)
1902  return status;
1903 
1904  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1905  return STATUS_BUFFER_TOO_SMALL;
1906 
1907  Stream_Read_INT32(s, call->fmszGroupsIsNULL); /* fmszGroupsIsNULL (4 bytes) */
1908  Stream_Read_UINT32(s, call->cchGroups); /* cchGroups (4 bytes) */
1909  status =
1910  smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr, &(call->handles.hContext));
1911 
1912  if (status != SCARD_S_SUCCESS)
1913  return status;
1914 
1915  smartcard_trace_list_reader_groups_call(call, unicode);
1916  return SCARD_S_SUCCESS;
1917 }
1918 
1919 LONG smartcard_pack_list_reader_groups_return(wStream* s, const ListReaderGroups_Return* ret,
1920  BOOL unicode)
1921 {
1922  LONG status = 0;
1923  DWORD cBytes = ret->cBytes;
1924  UINT32 index = 0;
1925 
1926  smartcard_trace_list_reader_groups_return(ret, unicode);
1927  if (ret->ReturnCode != SCARD_S_SUCCESS)
1928  cBytes = 0;
1929  if (cBytes == SCARD_AUTOALLOCATE)
1930  cBytes = 0;
1931 
1932  if (!Stream_EnsureRemainingCapacity(s, 4))
1933  return SCARD_E_NO_MEMORY;
1934 
1935  Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
1936  if (!smartcard_ndr_pointer_write(s, &index, cBytes))
1937  return SCARD_E_NO_MEMORY;
1938 
1939  status = smartcard_ndr_write(s, ret->msz, cBytes, 1, NDR_PTR_SIMPLE);
1940  if (status != SCARD_S_SUCCESS)
1941  return status;
1942  return ret->ReturnCode;
1943 }
1944 
1945 LONG smartcard_unpack_list_readers_call(wStream* s, ListReaders_Call* call, BOOL unicode)
1946 {
1947  UINT32 index = 0;
1948  UINT32 mszGroupsNdrPtr = 0;
1949  UINT32 pbContextNdrPtr = 0;
1950 
1951  call->mszGroups = NULL;
1952 
1953  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
1954  &pbContextNdrPtr);
1955  if (status != SCARD_S_SUCCESS)
1956  return status;
1957 
1958  if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1959  return STATUS_BUFFER_TOO_SMALL;
1960 
1961  Stream_Read_UINT32(s, call->cBytes); /* cBytes (4 bytes) */
1962  if (!smartcard_ndr_pointer_read(s, &index, &mszGroupsNdrPtr))
1963  return ERROR_INVALID_DATA;
1964  Stream_Read_INT32(s, call->fmszReadersIsNULL); /* fmszReadersIsNULL (4 bytes) */
1965  Stream_Read_UINT32(s, call->cchReaders); /* cchReaders (4 bytes) */
1966 
1967  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
1968  &(call->handles.hContext))))
1969  return status;
1970 
1971  if (mszGroupsNdrPtr)
1972  {
1973  status = smartcard_ndr_read(s, &call->mszGroups, call->cBytes, 1, NDR_PTR_SIMPLE);
1974  if (status != SCARD_S_SUCCESS)
1975  return status;
1976  }
1977 
1978  smartcard_trace_list_readers_call(call, unicode);
1979  return SCARD_S_SUCCESS;
1980 }
1981 
1982 LONG smartcard_pack_list_readers_return(wStream* s, const ListReaders_Return* ret, BOOL unicode)
1983 {
1984  LONG status = 0;
1985  UINT32 index = 0;
1986  UINT32 size = ret->cBytes;
1987 
1988  smartcard_trace_list_readers_return(ret, unicode);
1989  if (ret->ReturnCode != SCARD_S_SUCCESS)
1990  size = 0;
1991 
1992  if (!Stream_EnsureRemainingCapacity(s, 4))
1993  {
1994  WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
1995  return SCARD_F_INTERNAL_ERROR;
1996  }
1997 
1998  Stream_Write_UINT32(s, size); /* cBytes (4 bytes) */
1999  if (!smartcard_ndr_pointer_write(s, &index, size))
2000  return SCARD_E_NO_MEMORY;
2001 
2002  status = smartcard_ndr_write(s, ret->msz, size, 1, NDR_PTR_SIMPLE);
2003  if (status != SCARD_S_SUCCESS)
2004  return status;
2005  return ret->ReturnCode;
2006 }
2007 
2008 static LONG smartcard_unpack_connect_common(wStream* s, Connect_Common_Call* common, UINT32* index,
2009  UINT32* ppbContextNdrPtr)
2010 {
2011  LONG status = smartcard_unpack_redir_scard_context(s, &(common->handles.hContext), index,
2012  ppbContextNdrPtr);
2013  if (status != SCARD_S_SUCCESS)
2014  return status;
2015 
2016  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
2017  return STATUS_BUFFER_TOO_SMALL;
2018 
2019  Stream_Read_UINT32(s, common->dwShareMode); /* dwShareMode (4 bytes) */
2020  Stream_Read_UINT32(s, common->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
2021  return SCARD_S_SUCCESS;
2022 }
2023 
2024 LONG smartcard_unpack_connect_a_call(wStream* s, ConnectA_Call* call)
2025 {
2026  LONG status = 0;
2027  UINT32 index = 0;
2028  UINT32 pbContextNdrPtr = 0;
2029  call->szReader = NULL;
2030 
2031  if (!smartcard_ndr_pointer_read(s, &index, NULL))
2032  return ERROR_INVALID_DATA;
2033 
2034  if ((status = smartcard_unpack_connect_common(s, &(call->Common), &index, &pbContextNdrPtr)))
2035  {
2036  WLog_ERR(TAG, "smartcard_unpack_connect_common failed with error %" PRId32 "", status);
2037  return status;
2038  }
2039 
2040  status = smartcard_ndr_read_a(s, &call->szReader, NDR_PTR_FULL);
2041  if (status != SCARD_S_SUCCESS)
2042  return status;
2043 
2044  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
2045  &(call->Common.handles.hContext))))
2046  WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2047  status);
2048 
2049  smartcard_trace_connect_a_call(call);
2050  return status;
2051 }
2052 
2053 LONG smartcard_unpack_connect_w_call(wStream* s, ConnectW_Call* call)
2054 {
2055  LONG status = 0;
2056  UINT32 index = 0;
2057  UINT32 pbContextNdrPtr = 0;
2058 
2059  call->szReader = NULL;
2060 
2061  if (!smartcard_ndr_pointer_read(s, &index, NULL))
2062  return ERROR_INVALID_DATA;
2063 
2064  if ((status = smartcard_unpack_connect_common(s, &(call->Common), &index, &pbContextNdrPtr)))
2065  {
2066  WLog_ERR(TAG, "smartcard_unpack_connect_common failed with error %" PRId32 "", status);
2067  return status;
2068  }
2069 
2070  status = smartcard_ndr_read_w(s, &call->szReader, NDR_PTR_FULL);
2071  if (status != SCARD_S_SUCCESS)
2072  return status;
2073 
2074  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
2075  &(call->Common.handles.hContext))))
2076  WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2077  status);
2078 
2079  smartcard_trace_connect_w_call(call);
2080  return status;
2081 }
2082 
2083 LONG smartcard_pack_connect_return(wStream* s, const Connect_Return* ret)
2084 {
2085  LONG status = 0;
2086  DWORD index = 0;
2087 
2088  smartcard_trace_connect_return(ret);
2089 
2090  status = smartcard_pack_redir_scard_context(s, &ret->hContext, &index);
2091  if (status != SCARD_S_SUCCESS)
2092  return status;
2093 
2094  status = smartcard_pack_redir_scard_handle(s, &ret->hCard, &index);
2095  if (status != SCARD_S_SUCCESS)
2096  return status;
2097 
2098  if (!Stream_EnsureRemainingCapacity(s, 4))
2099  return SCARD_E_NO_MEMORY;
2100 
2101  Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
2102  status = smartcard_pack_redir_scard_context_ref(s, &ret->hContext);
2103  if (status != SCARD_S_SUCCESS)
2104  return status;
2105  return smartcard_pack_redir_scard_handle_ref(s, &(ret->hCard));
2106 }
2107 
2108 LONG smartcard_unpack_reconnect_call(wStream* s, Reconnect_Call* call)
2109 {
2110  UINT32 index = 0;
2111  UINT32 pbContextNdrPtr = 0;
2112  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
2113  &pbContextNdrPtr);
2114  if (status != SCARD_S_SUCCESS)
2115  return status;
2116 
2117  status = smartcard_unpack_redir_scard_handle(s, &(call->handles.hCard), &index);
2118  if (status != SCARD_S_SUCCESS)
2119  return status;
2120 
2121  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
2122  return STATUS_BUFFER_TOO_SMALL;
2123 
2124  Stream_Read_UINT32(s, call->dwShareMode); /* dwShareMode (4 bytes) */
2125  Stream_Read_UINT32(s, call->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
2126  Stream_Read_UINT32(s, call->dwInitialization); /* dwInitialization (4 bytes) */
2127 
2128  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
2129  &(call->handles.hContext))))
2130  {
2131  WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2132  status);
2133  return status;
2134  }
2135 
2136  if ((status = smartcard_unpack_redir_scard_handle_ref(s, &(call->handles.hCard))))
2137  WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "",
2138  status);
2139 
2140  smartcard_trace_reconnect_call(call);
2141  return status;
2142 }
2143 
2144 LONG smartcard_pack_reconnect_return(wStream* s, const Reconnect_Return* ret)
2145 {
2146  smartcard_trace_reconnect_return(ret);
2147 
2148  if (!Stream_EnsureRemainingCapacity(s, 4))
2149  return SCARD_E_NO_MEMORY;
2150  Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
2151  return ret->ReturnCode;
2152 }
2153 
2154 LONG smartcard_unpack_hcard_and_disposition_call(wStream* s, HCardAndDisposition_Call* call,
2155  const char* name)
2156 {
2157  UINT32 index = 0;
2158  UINT32 pbContextNdrPtr = 0;
2159 
2160  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
2161  &pbContextNdrPtr);
2162  if (status != SCARD_S_SUCCESS)
2163  return status;
2164 
2165  status = smartcard_unpack_redir_scard_handle(s, &(call->handles.hCard), &index);
2166  if (status != SCARD_S_SUCCESS)
2167  return status;
2168 
2169  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2170  return STATUS_BUFFER_TOO_SMALL;
2171 
2172  Stream_Read_UINT32(s, call->dwDisposition); /* dwDisposition (4 bytes) */
2173 
2174  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
2175  &(call->handles.hContext))))
2176  return status;
2177 
2178  if ((status = smartcard_unpack_redir_scard_handle_ref(s, &(call->handles.hCard))))
2179  return status;
2180 
2181  smartcard_trace_hcard_and_disposition_call(call, name);
2182  return status;
2183 }
2184 
2185 static void smartcard_trace_get_status_change_a_call(const GetStatusChangeA_Call* call)
2186 {
2187  if (!WLog_IsLevelActive(WLog_Get(TAG), g_LogLevel))
2188  return;
2189 
2190  WLog_LVL(TAG, g_LogLevel, "GetStatusChangeA_Call {");
2191  smartcard_log_context(TAG, &call->handles.hContext);
2192 
2193  WLog_LVL(TAG, g_LogLevel, "dwTimeOut: 0x%08" PRIX32 " cReaders: %" PRIu32 "", call->dwTimeOut,
2194  call->cReaders);
2195 
2196  for (UINT32 index = 0; index < call->cReaders; index++)
2197  {
2198  LPSCARD_READERSTATEA readerState = &call->rgReaderStates[index];
2199  WLog_LVL(TAG, g_LogLevel, "\t[%" PRIu32 "]: szReader: %s cbAtr: %" PRIu32 "", index,
2200  readerState->szReader, readerState->cbAtr);
2201  char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
2202  char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
2203  WLog_LVL(TAG, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
2204  szCurrentState, readerState->dwCurrentState);
2205  WLog_LVL(TAG, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
2206  szEventState, readerState->dwEventState);
2207  free(szCurrentState);
2208  free(szEventState);
2209  }
2210 
2211  WLog_LVL(TAG, g_LogLevel, "}");
2212 }
2213 
2214 static LONG smartcard_unpack_reader_state_a(wStream* s, LPSCARD_READERSTATEA* ppcReaders,
2215  UINT32 cReaders, UINT32* ptrIndex)
2216 {
2217  LONG status = SCARD_E_NO_MEMORY;
2218 
2219  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2220  return status;
2221 
2222  const UINT32 len = Stream_Get_UINT32(s);
2223  if (len != cReaders)
2224  {
2225  WLog_ERR(TAG, "Count mismatch when reading LPSCARD_READERSTATEA");
2226  return status;
2227  }
2228 
2229  LPSCARD_READERSTATEA rgReaderStates =
2230  (LPSCARD_READERSTATEA)calloc(cReaders, sizeof(SCARD_READERSTATEA));
2231  BOOL* states = calloc(cReaders, sizeof(BOOL));
2232  if (!rgReaderStates || !states)
2233  goto fail;
2234  status = ERROR_INVALID_DATA;
2235 
2236  for (UINT32 index = 0; index < cReaders; index++)
2237  {
2238  UINT32 ptr = UINT32_MAX;
2239  LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2240 
2241  if (!Stream_CheckAndLogRequiredLength(TAG, s, 52))
2242  goto fail;
2243 
2244  if (!smartcard_ndr_pointer_read(s, ptrIndex, &ptr))
2245  {
2246  if (ptr != 0)
2247  goto fail;
2248  }
2249  /* Ignore NULL length strings */
2250  states[index] = ptr != 0;
2251  Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2252  Stream_Read_UINT32(s, readerState->dwEventState); /* dwEventState (4 bytes) */
2253  Stream_Read_UINT32(s, readerState->cbAtr); /* cbAtr (4 bytes) */
2254  Stream_Read(s, readerState->rgbAtr, 36); /* rgbAtr [0..36] (36 bytes) */
2255  }
2256 
2257  for (UINT32 index = 0; index < cReaders; index++)
2258  {
2259  LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2260 
2261  /* Ignore empty strings */
2262  if (!states[index])
2263  continue;
2264  status = smartcard_ndr_read_a(s, &readerState->szReader, NDR_PTR_FULL);
2265  if (status != SCARD_S_SUCCESS)
2266  goto fail;
2267  }
2268 
2269  *ppcReaders = rgReaderStates;
2270  free(states);
2271  return SCARD_S_SUCCESS;
2272 fail:
2273  if (rgReaderStates)
2274  {
2275  for (UINT32 index = 0; index < cReaders; index++)
2276  {
2277  LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2278  free(readerState->szReader);
2279  }
2280  }
2281  free(rgReaderStates);
2282  free(states);
2283  return status;
2284 }
2285 
2286 static LONG smartcard_unpack_reader_state_w(wStream* s, LPSCARD_READERSTATEW* ppcReaders,
2287  UINT32 cReaders, UINT32* ptrIndex)
2288 {
2289  LONG status = SCARD_E_NO_MEMORY;
2290 
2291  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2292  return status;
2293 
2294  const UINT32 len = Stream_Get_UINT32(s);
2295  if (len != cReaders)
2296  {
2297  WLog_ERR(TAG, "Count mismatch when reading LPSCARD_READERSTATEW");
2298  return status;
2299  }
2300 
2301  LPSCARD_READERSTATEW rgReaderStates =
2302  (LPSCARD_READERSTATEW)calloc(cReaders, sizeof(SCARD_READERSTATEW));
2303  BOOL* states = calloc(cReaders, sizeof(BOOL));
2304 
2305  if (!rgReaderStates || !states)
2306  goto fail;
2307 
2308  status = ERROR_INVALID_DATA;
2309  for (UINT32 index = 0; index < cReaders; index++)
2310  {
2311  UINT32 ptr = UINT32_MAX;
2312  LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2313 
2314  if (!Stream_CheckAndLogRequiredLength(TAG, s, 52))
2315  goto fail;
2316 
2317  if (!smartcard_ndr_pointer_read(s, ptrIndex, &ptr))
2318  {
2319  if (ptr != 0)
2320  goto fail;
2321  }
2322  /* Ignore NULL length strings */
2323  states[index] = ptr != 0;
2324  Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2325  Stream_Read_UINT32(s, readerState->dwEventState); /* dwEventState (4 bytes) */
2326  Stream_Read_UINT32(s, readerState->cbAtr); /* cbAtr (4 bytes) */
2327  Stream_Read(s, readerState->rgbAtr, 36); /* rgbAtr [0..36] (36 bytes) */
2328  }
2329 
2330  for (UINT32 index = 0; index < cReaders; index++)
2331  {
2332  LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2333 
2334  /* Skip NULL pointers */
2335  if (!states[index])
2336  continue;
2337 
2338  status = smartcard_ndr_read_w(s, &readerState->szReader, NDR_PTR_FULL);
2339  if (status != SCARD_S_SUCCESS)
2340  goto fail;
2341  }
2342 
2343  *ppcReaders = rgReaderStates;
2344  free(states);
2345  return SCARD_S_SUCCESS;
2346 fail:
2347  if (rgReaderStates)
2348  {
2349  for (UINT32 index = 0; index < cReaders; index++)
2350  {
2351  LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2352  free(readerState->szReader);
2353  }
2354  }
2355  free(rgReaderStates);
2356  free(states);
2357  return status;
2358 }
2359 
2360 /******************************************************************************/
2361 /************************************* End Trace Functions ********************/
2362 /******************************************************************************/
2363 
2364 LONG smartcard_unpack_get_status_change_a_call(wStream* s, GetStatusChangeA_Call* call)
2365 {
2366  UINT32 ndrPtr = 0;
2367  UINT32 index = 0;
2368  UINT32 pbContextNdrPtr = 0;
2369 
2370  call->rgReaderStates = NULL;
2371 
2372  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
2373  &pbContextNdrPtr);
2374  if (status != SCARD_S_SUCCESS)
2375  return status;
2376 
2377  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
2378  return STATUS_BUFFER_TOO_SMALL;
2379 
2380  Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2381  Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */
2382  if (!smartcard_ndr_pointer_read(s, &index, &ndrPtr))
2383  return ERROR_INVALID_DATA;
2384 
2385  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
2386  &(call->handles.hContext))))
2387  return status;
2388 
2389  if (ndrPtr)
2390  {
2391  status = smartcard_unpack_reader_state_a(s, &call->rgReaderStates, call->cReaders, &index);
2392  if (status != SCARD_S_SUCCESS)
2393  return status;
2394  }
2395 
2396  smartcard_trace_get_status_change_a_call(call);
2397  return SCARD_S_SUCCESS;
2398 }
2399 
2400 LONG smartcard_unpack_get_status_change_w_call(wStream* s, GetStatusChangeW_Call* call)
2401 {
2402  UINT32 ndrPtr = 0;
2403  UINT32 index = 0;
2404  UINT32 pbContextNdrPtr = 0;
2405 
2406  call->rgReaderStates = NULL;
2407 
2408  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
2409  &pbContextNdrPtr);
2410  if (status != SCARD_S_SUCCESS)
2411  return status;
2412 
2413  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
2414  return STATUS_BUFFER_TOO_SMALL;
2415 
2416  Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2417  Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */
2418  if (!smartcard_ndr_pointer_read(s, &index, &ndrPtr))
2419  return ERROR_INVALID_DATA;
2420 
2421  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
2422  &(call->handles.hContext))))
2423  return status;
2424 
2425  if (ndrPtr)
2426  {
2427  status = smartcard_unpack_reader_state_w(s, &call->rgReaderStates, call->cReaders, &index);
2428  if (status != SCARD_S_SUCCESS)
2429  return status;
2430  }
2431 
2432  smartcard_trace_get_status_change_w_call(call);
2433  return SCARD_S_SUCCESS;
2434 }
2435 
2436 LONG smartcard_pack_get_status_change_return(wStream* s, const GetStatusChange_Return* ret,
2437  BOOL unicode)
2438 {
2439  LONG status = 0;
2440  DWORD cReaders = ret->cReaders;
2441  UINT32 index = 0;
2442 
2443  smartcard_trace_get_status_change_return(ret, unicode);
2444  if (ret->ReturnCode != SCARD_S_SUCCESS)
2445  cReaders = 0;
2446  if (cReaders == SCARD_AUTOALLOCATE)
2447  cReaders = 0;
2448 
2449  if (!Stream_EnsureRemainingCapacity(s, 4))
2450  return SCARD_E_NO_MEMORY;
2451 
2452  Stream_Write_UINT32(s, cReaders); /* cReaders (4 bytes) */
2453  if (!smartcard_ndr_pointer_write(s, &index, cReaders))
2454  return SCARD_E_NO_MEMORY;
2455  status = smartcard_ndr_write_state(s, ret->rgReaderStates, cReaders, NDR_PTR_SIMPLE);
2456  if (status != SCARD_S_SUCCESS)
2457  return status;
2458  return ret->ReturnCode;
2459 }
2460 
2461 LONG smartcard_unpack_state_call(wStream* s, State_Call* call)
2462 {
2463  UINT32 index = 0;
2464  UINT32 pbContextNdrPtr = 0;
2465  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
2466  &pbContextNdrPtr);
2467  if (status != SCARD_S_SUCCESS)
2468  return status;
2469 
2470  status = smartcard_unpack_redir_scard_handle(s, &(call->handles.hCard), &index);
2471  if (status != SCARD_S_SUCCESS)
2472  return status;
2473 
2474  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
2475  return STATUS_BUFFER_TOO_SMALL;
2476 
2477  Stream_Read_INT32(s, call->fpbAtrIsNULL); /* fpbAtrIsNULL (4 bytes) */
2478  Stream_Read_UINT32(s, call->cbAtrLen); /* cbAtrLen (4 bytes) */
2479 
2480  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
2481  &(call->handles.hContext))))
2482  return status;
2483 
2484  if ((status = smartcard_unpack_redir_scard_handle_ref(s, &(call->handles.hCard))))
2485  return status;
2486 
2487  return status;
2488 }
2489 
2490 LONG smartcard_pack_state_return(wStream* s, const State_Return* ret)
2491 {
2492  LONG status = 0;
2493  DWORD cbAtrLen = ret->cbAtrLen;
2494  UINT32 index = 0;
2495 
2496  smartcard_trace_state_return(ret);
2497  if (ret->ReturnCode != SCARD_S_SUCCESS)
2498  cbAtrLen = 0;
2499  if (cbAtrLen == SCARD_AUTOALLOCATE)
2500  cbAtrLen = 0;
2501 
2502  Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */
2503  Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
2504  Stream_Write_UINT32(s, cbAtrLen); /* cbAtrLen (4 bytes) */
2505  if (!smartcard_ndr_pointer_write(s, &index, cbAtrLen))
2506  return SCARD_E_NO_MEMORY;
2507  status = smartcard_ndr_write(s, ret->rgAtr, cbAtrLen, 1, NDR_PTR_SIMPLE);
2508  if (status != SCARD_S_SUCCESS)
2509  return status;
2510  return ret->ReturnCode;
2511 }
2512 
2513 LONG smartcard_unpack_status_call(wStream* s, Status_Call* call, BOOL unicode)
2514 {
2515  UINT32 index = 0;
2516  UINT32 pbContextNdrPtr = 0;
2517 
2518  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
2519  &pbContextNdrPtr);
2520  if (status != SCARD_S_SUCCESS)
2521  return status;
2522 
2523  status = smartcard_unpack_redir_scard_handle(s, &(call->handles.hCard), &index);
2524  if (status != SCARD_S_SUCCESS)
2525  return status;
2526 
2527  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
2528  return STATUS_BUFFER_TOO_SMALL;
2529 
2530  Stream_Read_INT32(s, call->fmszReaderNamesIsNULL); /* fmszReaderNamesIsNULL (4 bytes) */
2531  Stream_Read_UINT32(s, call->cchReaderLen); /* cchReaderLen (4 bytes) */
2532  Stream_Read_UINT32(s, call->cbAtrLen); /* cbAtrLen (4 bytes) */
2533 
2534  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
2535  &(call->handles.hContext))))
2536  return status;
2537 
2538  if ((status = smartcard_unpack_redir_scard_handle_ref(s, &(call->handles.hCard))))
2539  return status;
2540 
2541  smartcard_trace_status_call(call, unicode);
2542  return status;
2543 }
2544 
2545 LONG smartcard_pack_status_return(wStream* s, const Status_Return* ret, BOOL unicode)
2546 {
2547  LONG status = 0;
2548  UINT32 index = 0;
2549  DWORD cBytes = ret->cBytes;
2550 
2551  smartcard_trace_status_return(ret, unicode);
2552  if (ret->ReturnCode != SCARD_S_SUCCESS)
2553  cBytes = 0;
2554  if (cBytes == SCARD_AUTOALLOCATE)
2555  cBytes = 0;
2556 
2557  if (!Stream_EnsureRemainingCapacity(s, 4))
2558  return SCARD_F_INTERNAL_ERROR;
2559 
2560  Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
2561  if (!smartcard_ndr_pointer_write(s, &index, cBytes))
2562  return SCARD_E_NO_MEMORY;
2563 
2564  if (!Stream_EnsureRemainingCapacity(s, 44))
2565  return SCARD_F_INTERNAL_ERROR;
2566 
2567  Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */
2568  Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
2569  Stream_Write(s, ret->pbAtr, sizeof(ret->pbAtr)); /* pbAtr (32 bytes) */
2570  Stream_Write_UINT32(s, ret->cbAtrLen); /* cbAtrLen (4 bytes) */
2571  status = smartcard_ndr_write(s, ret->mszReaderNames, cBytes, 1, NDR_PTR_SIMPLE);
2572  if (status != SCARD_S_SUCCESS)
2573  return status;
2574  return ret->ReturnCode;
2575 }
2576 
2577 LONG smartcard_unpack_get_attrib_call(wStream* s, GetAttrib_Call* call)
2578 {
2579  UINT32 index = 0;
2580  UINT32 pbContextNdrPtr = 0;
2581 
2582  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
2583  &pbContextNdrPtr);
2584  if (status != SCARD_S_SUCCESS)
2585  return status;
2586 
2587  status = smartcard_unpack_redir_scard_handle(s, &(call->handles.hCard), &index);
2588  if (status != SCARD_S_SUCCESS)
2589  return status;
2590 
2591  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
2592  return STATUS_BUFFER_TOO_SMALL;
2593 
2594  Stream_Read_UINT32(s, call->dwAttrId); /* dwAttrId (4 bytes) */
2595  Stream_Read_INT32(s, call->fpbAttrIsNULL); /* fpbAttrIsNULL (4 bytes) */
2596  Stream_Read_UINT32(s, call->cbAttrLen); /* cbAttrLen (4 bytes) */
2597 
2598  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
2599  &(call->handles.hContext))))
2600  return status;
2601 
2602  if ((status = smartcard_unpack_redir_scard_handle_ref(s, &(call->handles.hCard))))
2603  return status;
2604 
2605  smartcard_trace_get_attrib_call(call);
2606  return status;
2607 }
2608 
2609 LONG smartcard_pack_get_attrib_return(wStream* s, const GetAttrib_Return* ret, DWORD dwAttrId,
2610  DWORD cbAttrCallLen)
2611 {
2612  LONG status = 0;
2613  DWORD cbAttrLen = 0;
2614  UINT32 index = 0;
2615  smartcard_trace_get_attrib_return(ret, dwAttrId);
2616 
2617  if (!Stream_EnsureRemainingCapacity(s, 4))
2618  return SCARD_F_INTERNAL_ERROR;
2619 
2620  cbAttrLen = ret->cbAttrLen;
2621  if (ret->ReturnCode != SCARD_S_SUCCESS)
2622  cbAttrLen = 0;
2623  if (cbAttrLen == SCARD_AUTOALLOCATE)
2624  cbAttrLen = 0;
2625 
2626  if (ret->pbAttr)
2627  {
2628  if (cbAttrCallLen < cbAttrLen)
2629  cbAttrLen = cbAttrCallLen;
2630  }
2631  Stream_Write_UINT32(s, cbAttrLen); /* cbAttrLen (4 bytes) */
2632  if (!smartcard_ndr_pointer_write(s, &index, cbAttrLen))
2633  return SCARD_E_NO_MEMORY;
2634 
2635  status = smartcard_ndr_write(s, ret->pbAttr, cbAttrLen, 1, NDR_PTR_SIMPLE);
2636  if (status != SCARD_S_SUCCESS)
2637  return status;
2638  return ret->ReturnCode;
2639 }
2640 
2641 LONG smartcard_unpack_control_call(wStream* s, Control_Call* call)
2642 {
2643  UINT32 index = 0;
2644  UINT32 pvInBufferNdrPtr = 0;
2645  UINT32 pbContextNdrPtr = 0;
2646 
2647  call->pvInBuffer = NULL;
2648 
2649  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
2650  &pbContextNdrPtr);
2651  if (status != SCARD_S_SUCCESS)
2652  return status;
2653 
2654  status = smartcard_unpack_redir_scard_handle(s, &(call->handles.hCard), &index);
2655  if (status != SCARD_S_SUCCESS)
2656  return status;
2657 
2658  if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
2659  return STATUS_BUFFER_TOO_SMALL;
2660 
2661  Stream_Read_UINT32(s, call->dwControlCode); /* dwControlCode (4 bytes) */
2662  Stream_Read_UINT32(s, call->cbInBufferSize); /* cbInBufferSize (4 bytes) */
2663  if (!smartcard_ndr_pointer_read(s, &index, &pvInBufferNdrPtr)) /* pvInBufferNdrPtr (4 bytes) */
2664  return ERROR_INVALID_DATA;
2665  Stream_Read_INT32(s, call->fpvOutBufferIsNULL); /* fpvOutBufferIsNULL (4 bytes) */
2666  Stream_Read_UINT32(s, call->cbOutBufferSize); /* cbOutBufferSize (4 bytes) */
2667 
2668  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
2669  &(call->handles.hContext))))
2670  return status;
2671 
2672  if ((status = smartcard_unpack_redir_scard_handle_ref(s, &(call->handles.hCard))))
2673  return status;
2674 
2675  if (pvInBufferNdrPtr)
2676  {
2677  status = smartcard_ndr_read(s, &call->pvInBuffer, call->cbInBufferSize, 1, NDR_PTR_SIMPLE);
2678  if (status != SCARD_S_SUCCESS)
2679  return status;
2680  }
2681 
2682  smartcard_trace_control_call(call);
2683  return SCARD_S_SUCCESS;
2684 }
2685 
2686 LONG smartcard_pack_control_return(wStream* s, const Control_Return* ret)
2687 {
2688  LONG status = 0;
2689  DWORD cbDataLen = ret->cbOutBufferSize;
2690  UINT32 index = 0;
2691 
2692  smartcard_trace_control_return(ret);
2693  if (ret->ReturnCode != SCARD_S_SUCCESS)
2694  cbDataLen = 0;
2695  if (cbDataLen == SCARD_AUTOALLOCATE)
2696  cbDataLen = 0;
2697 
2698  if (!Stream_EnsureRemainingCapacity(s, 4))
2699  return SCARD_F_INTERNAL_ERROR;
2700 
2701  Stream_Write_UINT32(s, cbDataLen); /* cbOutBufferSize (4 bytes) */
2702  if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
2703  return SCARD_E_NO_MEMORY;
2704 
2705  status = smartcard_ndr_write(s, ret->pvOutBuffer, cbDataLen, 1, NDR_PTR_SIMPLE);
2706  if (status != SCARD_S_SUCCESS)
2707  return status;
2708  return ret->ReturnCode;
2709 }
2710 
2711 LONG smartcard_unpack_transmit_call(wStream* s, Transmit_Call* call)
2712 {
2713  UINT32 length = 0;
2714  BYTE* pbExtraBytes = NULL;
2715  UINT32 pbExtraBytesNdrPtr = 0;
2716  UINT32 pbSendBufferNdrPtr = 0;
2717  UINT32 pioRecvPciNdrPtr = 0;
2718  SCardIO_Request ioSendPci;
2719  SCardIO_Request ioRecvPci;
2720  UINT32 index = 0;
2721  UINT32 pbContextNdrPtr = 0;
2722 
2723  call->pioSendPci = NULL;
2724  call->pioRecvPci = NULL;
2725  call->pbSendBuffer = NULL;
2726 
2727  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
2728  &pbContextNdrPtr);
2729  if (status != SCARD_S_SUCCESS)
2730  return status;
2731 
2732  status = smartcard_unpack_redir_scard_handle(s, &(call->handles.hCard), &index);
2733  if (status != SCARD_S_SUCCESS)
2734  return status;
2735 
2736  if (!Stream_CheckAndLogRequiredLength(TAG, s, 32))
2737  return STATUS_BUFFER_TOO_SMALL;
2738 
2739  Stream_Read_UINT32(s, ioSendPci.dwProtocol); /* dwProtocol (4 bytes) */
2740  Stream_Read_UINT32(s, ioSendPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
2741  if (!smartcard_ndr_pointer_read(s, &index,
2742  &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
2743  return ERROR_INVALID_DATA;
2744 
2745  Stream_Read_UINT32(s, call->cbSendLength); /* cbSendLength (4 bytes) */
2746  if (!smartcard_ndr_pointer_read(s, &index,
2747  &pbSendBufferNdrPtr)) /* pbSendBufferNdrPtr (4 bytes) */
2748  return ERROR_INVALID_DATA;
2749 
2750  if (!smartcard_ndr_pointer_read(s, &index, &pioRecvPciNdrPtr)) /* pioRecvPciNdrPtr (4 bytes) */
2751  return ERROR_INVALID_DATA;
2752 
2753  Stream_Read_INT32(s, call->fpbRecvBufferIsNULL); /* fpbRecvBufferIsNULL (4 bytes) */
2754  Stream_Read_UINT32(s, call->cbRecvLength); /* cbRecvLength (4 bytes) */
2755 
2756  if (ioSendPci.cbExtraBytes > 1024)
2757  {
2758  WLog_WARN(TAG,
2759  "Transmit_Call ioSendPci.cbExtraBytes is out of bounds: %" PRIu32 " (max: 1024)",
2760  ioSendPci.cbExtraBytes);
2761  return STATUS_INVALID_PARAMETER;
2762  }
2763 
2764  if (call->cbSendLength > 66560)
2765  {
2766  WLog_WARN(TAG, "Transmit_Call cbSendLength is out of bounds: %" PRIu32 " (max: 66560)",
2767  ioSendPci.cbExtraBytes);
2768  return STATUS_INVALID_PARAMETER;
2769  }
2770 
2771  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
2772  &(call->handles.hContext))))
2773  return status;
2774 
2775  if ((status = smartcard_unpack_redir_scard_handle_ref(s, &(call->handles.hCard))))
2776  return status;
2777 
2778  if (ioSendPci.cbExtraBytes && !pbExtraBytesNdrPtr)
2779  {
2780  WLog_WARN(
2781  TAG, "Transmit_Call ioSendPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
2782  return STATUS_INVALID_PARAMETER;
2783  }
2784 
2785  if (pbExtraBytesNdrPtr)
2786  {
2787  // TODO: Use unified pointer reading
2788  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2789  return STATUS_BUFFER_TOO_SMALL;
2790 
2791  Stream_Read_UINT32(s, length); /* Length (4 bytes) */
2792 
2793  if (!Stream_CheckAndLogRequiredLength(TAG, s, ioSendPci.cbExtraBytes))
2794  return STATUS_BUFFER_TOO_SMALL;
2795 
2796  ioSendPci.pbExtraBytes = Stream_Pointer(s);
2797  call->pioSendPci =
2798  (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioSendPci.cbExtraBytes);
2799 
2800  if (!call->pioSendPci)
2801  {
2802  WLog_WARN(TAG, "Transmit_Call out of memory error (pioSendPci)");
2803  return STATUS_NO_MEMORY;
2804  }
2805 
2806  call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
2807  call->pioSendPci->cbPciLength = (DWORD)(ioSendPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
2808  pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
2809  Stream_Read(s, pbExtraBytes, ioSendPci.cbExtraBytes);
2810  smartcard_unpack_read_size_align(s, ioSendPci.cbExtraBytes, 4);
2811  }
2812  else
2813  {
2814  call->pioSendPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
2815 
2816  if (!call->pioSendPci)
2817  {
2818  WLog_WARN(TAG, "Transmit_Call out of memory error (pioSendPci)");
2819  return STATUS_NO_MEMORY;
2820  }
2821 
2822  call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
2823  call->pioSendPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
2824  }
2825 
2826  if (pbSendBufferNdrPtr)
2827  {
2828  status = smartcard_ndr_read(s, &call->pbSendBuffer, call->cbSendLength, 1, NDR_PTR_SIMPLE);
2829  if (status != SCARD_S_SUCCESS)
2830  return status;
2831  }
2832 
2833  if (pioRecvPciNdrPtr)
2834  {
2835  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
2836  return STATUS_BUFFER_TOO_SMALL;
2837 
2838  Stream_Read_UINT32(s, ioRecvPci.dwProtocol); /* dwProtocol (4 bytes) */
2839  Stream_Read_UINT32(s, ioRecvPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
2840  if (!smartcard_ndr_pointer_read(s, &index,
2841  &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
2842  return ERROR_INVALID_DATA;
2843 
2844  if (ioRecvPci.cbExtraBytes && !pbExtraBytesNdrPtr)
2845  {
2846  WLog_WARN(
2847  TAG,
2848  "Transmit_Call ioRecvPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
2849  return STATUS_INVALID_PARAMETER;
2850  }
2851 
2852  if (pbExtraBytesNdrPtr)
2853  {
2854  // TODO: Unify ndr pointer reading
2855  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2856  return STATUS_BUFFER_TOO_SMALL;
2857 
2858  Stream_Read_UINT32(s, length); /* Length (4 bytes) */
2859 
2860  if (ioRecvPci.cbExtraBytes > 1024)
2861  {
2862  WLog_WARN(TAG,
2863  "Transmit_Call ioRecvPci.cbExtraBytes is out of bounds: %" PRIu32
2864  " (max: 1024)",
2865  ioRecvPci.cbExtraBytes);
2866  return STATUS_INVALID_PARAMETER;
2867  }
2868 
2869  if (length != ioRecvPci.cbExtraBytes)
2870  {
2871  WLog_WARN(TAG,
2872  "Transmit_Call unexpected length: Actual: %" PRIu32 ", Expected: %" PRIu32
2873  " (ioRecvPci.cbExtraBytes)",
2874  length, ioRecvPci.cbExtraBytes);
2875  return STATUS_INVALID_PARAMETER;
2876  }
2877 
2878  if (!Stream_CheckAndLogRequiredLength(TAG, s, ioRecvPci.cbExtraBytes))
2879  return STATUS_BUFFER_TOO_SMALL;
2880 
2881  ioRecvPci.pbExtraBytes = Stream_Pointer(s);
2882  call->pioRecvPci =
2883  (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioRecvPci.cbExtraBytes);
2884 
2885  if (!call->pioRecvPci)
2886  {
2887  WLog_WARN(TAG, "Transmit_Call out of memory error (pioRecvPci)");
2888  return STATUS_NO_MEMORY;
2889  }
2890 
2891  call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
2892  call->pioRecvPci->cbPciLength =
2893  (DWORD)(ioRecvPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
2894  pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
2895  Stream_Read(s, pbExtraBytes, ioRecvPci.cbExtraBytes);
2896  smartcard_unpack_read_size_align(s, ioRecvPci.cbExtraBytes, 4);
2897  }
2898  else
2899  {
2900  call->pioRecvPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
2901 
2902  if (!call->pioRecvPci)
2903  {
2904  WLog_WARN(TAG, "Transmit_Call out of memory error (pioRecvPci)");
2905  return STATUS_NO_MEMORY;
2906  }
2907 
2908  call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
2909  call->pioRecvPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
2910  }
2911  }
2912 
2913  smartcard_trace_transmit_call(call);
2914  return SCARD_S_SUCCESS;
2915 }
2916 
2917 LONG smartcard_pack_transmit_return(wStream* s, const Transmit_Return* ret)
2918 {
2919  LONG status = 0;
2920  UINT32 index = 0;
2921  LONG error = 0;
2922  UINT32 cbRecvLength = ret->cbRecvLength;
2923  UINT32 cbRecvPci = ret->pioRecvPci ? ret->pioRecvPci->cbPciLength : 0;
2924 
2925  smartcard_trace_transmit_return(ret);
2926 
2927  if (!ret->pbRecvBuffer)
2928  cbRecvLength = 0;
2929 
2930  if (!smartcard_ndr_pointer_write(s, &index, cbRecvPci))
2931  return SCARD_E_NO_MEMORY;
2932  if (!Stream_EnsureRemainingCapacity(s, 4))
2933  return SCARD_E_NO_MEMORY;
2934  Stream_Write_UINT32(s, cbRecvLength); /* cbRecvLength (4 bytes) */
2935  if (!smartcard_ndr_pointer_write(s, &index, cbRecvLength))
2936  return SCARD_E_NO_MEMORY;
2937 
2938  if (ret->pioRecvPci)
2939  {
2940  UINT32 cbExtraBytes = (UINT32)(ret->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
2941  BYTE* pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
2942 
2943  if (!Stream_EnsureRemainingCapacity(s, cbExtraBytes + 16))
2944  {
2945  WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
2946  return SCARD_F_INTERNAL_ERROR;
2947  }
2948 
2949  Stream_Write_UINT32(s, ret->pioRecvPci->dwProtocol); /* dwProtocol (4 bytes) */
2950  Stream_Write_UINT32(s, cbExtraBytes); /* cbExtraBytes (4 bytes) */
2951  if (!smartcard_ndr_pointer_write(s, &index, cbExtraBytes))
2952  return SCARD_E_NO_MEMORY;
2953  error = smartcard_ndr_write(s, pbExtraBytes, cbExtraBytes, 1, NDR_PTR_SIMPLE);
2954  if (error)
2955  return error;
2956  }
2957 
2958  status = smartcard_ndr_write(s, ret->pbRecvBuffer, ret->cbRecvLength, 1, NDR_PTR_SIMPLE);
2959  if (status != SCARD_S_SUCCESS)
2960  return status;
2961  return ret->ReturnCode;
2962 }
2963 
2964 LONG smartcard_unpack_locate_cards_by_atr_a_call(wStream* s, LocateCardsByATRA_Call* call)
2965 {
2966  UINT32 rgReaderStatesNdrPtr = 0;
2967  UINT32 rgAtrMasksNdrPtr = 0;
2968  UINT32 index = 0;
2969  UINT32 pbContextNdrPtr = 0;
2970 
2971  call->rgReaderStates = NULL;
2972 
2973  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
2974  &pbContextNdrPtr);
2975  if (status != SCARD_S_SUCCESS)
2976  return status;
2977 
2978  if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
2979  return STATUS_BUFFER_TOO_SMALL;
2980 
2981  Stream_Read_UINT32(s, call->cAtrs);
2982  if (!smartcard_ndr_pointer_read(s, &index, &rgAtrMasksNdrPtr))
2983  return ERROR_INVALID_DATA;
2984  Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */
2985  if (!smartcard_ndr_pointer_read(s, &index, &rgReaderStatesNdrPtr))
2986  return ERROR_INVALID_DATA;
2987 
2988  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
2989  &(call->handles.hContext))))
2990  return status;
2991 
2992  if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
2993  {
2994  WLog_WARN(TAG,
2995  "LocateCardsByATRA_Call rgAtrMasksNdrPtr (0x%08" PRIX32
2996  ") and cAtrs (0x%08" PRIX32 ") inconsistency",
2997  rgAtrMasksNdrPtr, call->cAtrs);
2998  return STATUS_INVALID_PARAMETER;
2999  }
3000 
3001  if (rgAtrMasksNdrPtr)
3002  {
3003  status = smartcard_ndr_read_atrmask(s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3004  if (status != SCARD_S_SUCCESS)
3005  return status;
3006  }
3007 
3008  if (rgReaderStatesNdrPtr)
3009  {
3010  status = smartcard_unpack_reader_state_a(s, &call->rgReaderStates, call->cReaders, &index);
3011  if (status != SCARD_S_SUCCESS)
3012  return status;
3013  }
3014 
3015  smartcard_trace_locate_cards_by_atr_a_call(call);
3016  return SCARD_S_SUCCESS;
3017 }
3018 
3019 LONG smartcard_unpack_context_and_two_strings_a_call(wStream* s, ContextAndTwoStringA_Call* call)
3020 {
3021  UINT32 sz1NdrPtr = 0;
3022  UINT32 sz2NdrPtr = 0;
3023  UINT32 index = 0;
3024  UINT32 pbContextNdrPtr = 0;
3025 
3026  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
3027  &pbContextNdrPtr);
3028  if (status != SCARD_S_SUCCESS)
3029  return status;
3030 
3031  if (!smartcard_ndr_pointer_read(s, &index, &sz1NdrPtr))
3032  return ERROR_INVALID_DATA;
3033  if (!smartcard_ndr_pointer_read(s, &index, &sz2NdrPtr))
3034  return ERROR_INVALID_DATA;
3035 
3036  status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr, &call->handles.hContext);
3037  if (status != SCARD_S_SUCCESS)
3038  return status;
3039 
3040  if (sz1NdrPtr)
3041  {
3042  status = smartcard_ndr_read_a(s, &call->sz1, NDR_PTR_FULL);
3043  if (status != SCARD_S_SUCCESS)
3044  return status;
3045  }
3046  if (sz2NdrPtr)
3047  {
3048  status = smartcard_ndr_read_a(s, &call->sz2, NDR_PTR_FULL);
3049  if (status != SCARD_S_SUCCESS)
3050  return status;
3051  }
3052  smartcard_trace_context_and_two_strings_a_call(call);
3053  return SCARD_S_SUCCESS;
3054 }
3055 
3056 LONG smartcard_unpack_context_and_two_strings_w_call(wStream* s, ContextAndTwoStringW_Call* call)
3057 {
3058  UINT32 sz1NdrPtr = 0;
3059  UINT32 sz2NdrPtr = 0;
3060  UINT32 index = 0;
3061  UINT32 pbContextNdrPtr = 0;
3062 
3063  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
3064  &pbContextNdrPtr);
3065  if (status != SCARD_S_SUCCESS)
3066  return status;
3067 
3068  if (!smartcard_ndr_pointer_read(s, &index, &sz1NdrPtr))
3069  return ERROR_INVALID_DATA;
3070  if (!smartcard_ndr_pointer_read(s, &index, &sz2NdrPtr))
3071  return ERROR_INVALID_DATA;
3072 
3073  status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr, &call->handles.hContext);
3074  if (status != SCARD_S_SUCCESS)
3075  return status;
3076 
3077  if (sz1NdrPtr)
3078  {
3079  status = smartcard_ndr_read_w(s, &call->sz1, NDR_PTR_FULL);
3080  if (status != SCARD_S_SUCCESS)
3081  return status;
3082  }
3083  if (sz2NdrPtr)
3084  {
3085  status = smartcard_ndr_read_w(s, &call->sz2, NDR_PTR_FULL);
3086  if (status != SCARD_S_SUCCESS)
3087  return status;
3088  }
3089  smartcard_trace_context_and_two_strings_w_call(call);
3090  return SCARD_S_SUCCESS;
3091 }
3092 
3093 LONG smartcard_unpack_locate_cards_a_call(wStream* s, LocateCardsA_Call* call)
3094 {
3095  UINT32 sz1NdrPtr = 0;
3096  UINT32 sz2NdrPtr = 0;
3097  UINT32 index = 0;
3098  UINT32 pbContextNdrPtr = 0;
3099 
3100  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
3101  &pbContextNdrPtr);
3102  if (status != SCARD_S_SUCCESS)
3103  return status;
3104 
3105  if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
3106  return STATUS_BUFFER_TOO_SMALL;
3107 
3108  Stream_Read_UINT32(s, call->cBytes);
3109  if (!smartcard_ndr_pointer_read(s, &index, &sz1NdrPtr))
3110  return ERROR_INVALID_DATA;
3111 
3112  Stream_Read_UINT32(s, call->cReaders);
3113  if (!smartcard_ndr_pointer_read(s, &index, &sz2NdrPtr))
3114  return ERROR_INVALID_DATA;
3115 
3116  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
3117  &(call->handles.hContext))))
3118  return status;
3119 
3120  if (sz1NdrPtr)
3121  {
3122  status =
3123  smartcard_ndr_read_fixed_string_a(s, &call->mszCards, call->cBytes, NDR_PTR_SIMPLE);
3124  if (status != SCARD_S_SUCCESS)
3125  return status;
3126  }
3127  if (sz2NdrPtr)
3128  {
3129  status = smartcard_unpack_reader_state_a(s, &call->rgReaderStates, call->cReaders, &index);
3130  if (status != SCARD_S_SUCCESS)
3131  return status;
3132  }
3133  smartcard_trace_locate_cards_a_call(call);
3134  return SCARD_S_SUCCESS;
3135 }
3136 
3137 LONG smartcard_unpack_locate_cards_w_call(wStream* s, LocateCardsW_Call* call)
3138 {
3139  UINT32 sz1NdrPtr = 0;
3140  UINT32 sz2NdrPtr = 0;
3141  UINT32 index = 0;
3142  UINT32 pbContextNdrPtr = 0;
3143 
3144  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
3145  &pbContextNdrPtr);
3146  if (status != SCARD_S_SUCCESS)
3147  return status;
3148 
3149  if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
3150  return STATUS_BUFFER_TOO_SMALL;
3151 
3152  Stream_Read_UINT32(s, call->cBytes);
3153  if (!smartcard_ndr_pointer_read(s, &index, &sz1NdrPtr))
3154  return ERROR_INVALID_DATA;
3155 
3156  Stream_Read_UINT32(s, call->cReaders);
3157  if (!smartcard_ndr_pointer_read(s, &index, &sz2NdrPtr))
3158  return ERROR_INVALID_DATA;
3159 
3160  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
3161  &(call->handles.hContext))))
3162  return status;
3163 
3164  if (sz1NdrPtr)
3165  {
3166  status =
3167  smartcard_ndr_read_fixed_string_w(s, &call->mszCards, call->cBytes, NDR_PTR_SIMPLE);
3168  if (status != SCARD_S_SUCCESS)
3169  return status;
3170  }
3171  if (sz2NdrPtr)
3172  {
3173  status = smartcard_unpack_reader_state_w(s, &call->rgReaderStates, call->cReaders, &index);
3174  if (status != SCARD_S_SUCCESS)
3175  return status;
3176  }
3177  smartcard_trace_locate_cards_w_call(call);
3178  return SCARD_S_SUCCESS;
3179 }
3180 
3181 LONG smartcard_unpack_set_attrib_call(wStream* s, SetAttrib_Call* call)
3182 {
3183  UINT32 index = 0;
3184  UINT32 ndrPtr = 0;
3185  UINT32 pbContextNdrPtr = 0;
3186 
3187  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
3188  &pbContextNdrPtr);
3189  if (status != SCARD_S_SUCCESS)
3190  return status;
3191  status = smartcard_unpack_redir_scard_handle(s, &(call->handles.hCard), &index);
3192  if (status != SCARD_S_SUCCESS)
3193  return status;
3194 
3195  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
3196  return STATUS_BUFFER_TOO_SMALL;
3197  Stream_Read_UINT32(s, call->dwAttrId);
3198  Stream_Read_UINT32(s, call->cbAttrLen);
3199 
3200  if (!smartcard_ndr_pointer_read(s, &index, &ndrPtr))
3201  return ERROR_INVALID_DATA;
3202 
3203  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
3204  &(call->handles.hContext))))
3205  return status;
3206 
3207  if ((status = smartcard_unpack_redir_scard_handle_ref(s, &(call->handles.hCard))))
3208  return status;
3209 
3210  if (ndrPtr)
3211  {
3212  // TODO: call->cbAttrLen was larger than the pointer value.
3213  // TODO: Maybe need to refine the checks?
3214  status = smartcard_ndr_read(s, &call->pbAttr, 0, 1, NDR_PTR_SIMPLE);
3215  if (status != SCARD_S_SUCCESS)
3216  return status;
3217  }
3218  smartcard_trace_set_attrib_call(call);
3219  return SCARD_S_SUCCESS;
3220 }
3221 
3222 LONG smartcard_unpack_locate_cards_by_atr_w_call(wStream* s, LocateCardsByATRW_Call* call)
3223 {
3224  UINT32 rgReaderStatesNdrPtr = 0;
3225  UINT32 rgAtrMasksNdrPtr = 0;
3226  UINT32 index = 0;
3227  UINT32 pbContextNdrPtr = 0;
3228 
3229  call->rgReaderStates = NULL;
3230 
3231  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
3232  &pbContextNdrPtr);
3233  if (status != SCARD_S_SUCCESS)
3234  return status;
3235 
3236  if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
3237  return STATUS_BUFFER_TOO_SMALL;
3238 
3239  Stream_Read_UINT32(s, call->cAtrs);
3240  if (!smartcard_ndr_pointer_read(s, &index, &rgAtrMasksNdrPtr))
3241  return ERROR_INVALID_DATA;
3242 
3243  Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */
3244  if (!smartcard_ndr_pointer_read(s, &index, &rgReaderStatesNdrPtr))
3245  return ERROR_INVALID_DATA;
3246 
3247  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
3248  &(call->handles.hContext))))
3249  return status;
3250 
3251  if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3252  {
3253  WLog_WARN(TAG,
3254  "LocateCardsByATRW_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3255  ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3256  rgAtrMasksNdrPtr, call->cAtrs);
3257  return STATUS_INVALID_PARAMETER;
3258  }
3259 
3260  if (rgAtrMasksNdrPtr)
3261  {
3262  status = smartcard_ndr_read_atrmask(s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3263  if (status != SCARD_S_SUCCESS)
3264  return status;
3265  }
3266 
3267  if (rgReaderStatesNdrPtr)
3268  {
3269  status = smartcard_unpack_reader_state_w(s, &call->rgReaderStates, call->cReaders, &index);
3270  if (status != SCARD_S_SUCCESS)
3271  return status;
3272  }
3273 
3274  smartcard_trace_locate_cards_by_atr_w_call(call);
3275  return SCARD_S_SUCCESS;
3276 }
3277 
3278 LONG smartcard_unpack_read_cache_a_call(wStream* s, ReadCacheA_Call* call)
3279 {
3280  UINT32 mszNdrPtr = 0;
3281  UINT32 contextNdrPtr = 0;
3282  UINT32 index = 0;
3283  UINT32 pbContextNdrPtr = 0;
3284 
3285  if (!smartcard_ndr_pointer_read(s, &index, &mszNdrPtr))
3286  return ERROR_INVALID_DATA;
3287 
3288  LONG status = smartcard_unpack_redir_scard_context(s, &(call->Common.handles.hContext), &index,
3289  &pbContextNdrPtr);
3290  if (status != SCARD_S_SUCCESS)
3291  return status;
3292 
3293  if (!smartcard_ndr_pointer_read(s, &index, &contextNdrPtr))
3294  return ERROR_INVALID_DATA;
3295 
3296  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
3297  return STATUS_BUFFER_TOO_SMALL;
3298  Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3299  Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
3300  Stream_Read_UINT32(s, call->Common.cbDataLen);
3301 
3302  call->szLookupName = NULL;
3303  if (mszNdrPtr)
3304  {
3305  status = smartcard_ndr_read_a(s, &call->szLookupName, NDR_PTR_FULL);
3306  if (status != SCARD_S_SUCCESS)
3307  return status;
3308  }
3309 
3310  status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
3311  &call->Common.handles.hContext);
3312  if (status != SCARD_S_SUCCESS)
3313  return status;
3314 
3315  if (contextNdrPtr)
3316  {
3317  status = smartcard_ndr_read_u(s, &call->Common.CardIdentifier);
3318  if (status != SCARD_S_SUCCESS)
3319  return status;
3320  }
3321  smartcard_trace_read_cache_a_call(call);
3322  return SCARD_S_SUCCESS;
3323 }
3324 
3325 LONG smartcard_unpack_read_cache_w_call(wStream* s, ReadCacheW_Call* call)
3326 {
3327  UINT32 mszNdrPtr = 0;
3328  UINT32 contextNdrPtr = 0;
3329  UINT32 index = 0;
3330  UINT32 pbContextNdrPtr = 0;
3331 
3332  if (!smartcard_ndr_pointer_read(s, &index, &mszNdrPtr))
3333  return ERROR_INVALID_DATA;
3334 
3335  LONG status = smartcard_unpack_redir_scard_context(s, &(call->Common.handles.hContext), &index,
3336  &pbContextNdrPtr);
3337  if (status != SCARD_S_SUCCESS)
3338  return status;
3339 
3340  if (!smartcard_ndr_pointer_read(s, &index, &contextNdrPtr))
3341  return ERROR_INVALID_DATA;
3342 
3343  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
3344  return STATUS_BUFFER_TOO_SMALL;
3345  Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3346  Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
3347  Stream_Read_UINT32(s, call->Common.cbDataLen);
3348 
3349  call->szLookupName = NULL;
3350  if (mszNdrPtr)
3351  {
3352  status = smartcard_ndr_read_w(s, &call->szLookupName, NDR_PTR_FULL);
3353  if (status != SCARD_S_SUCCESS)
3354  return status;
3355  }
3356 
3357  status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
3358  &call->Common.handles.hContext);
3359  if (status != SCARD_S_SUCCESS)
3360  return status;
3361 
3362  if (contextNdrPtr)
3363  {
3364  status = smartcard_ndr_read_u(s, &call->Common.CardIdentifier);
3365  if (status != SCARD_S_SUCCESS)
3366  return status;
3367  }
3368  smartcard_trace_read_cache_w_call(call);
3369  return SCARD_S_SUCCESS;
3370 }
3371 
3372 LONG smartcard_unpack_write_cache_a_call(wStream* s, WriteCacheA_Call* call)
3373 {
3374  UINT32 mszNdrPtr = 0;
3375  UINT32 contextNdrPtr = 0;
3376  UINT32 pbDataNdrPtr = 0;
3377  UINT32 index = 0;
3378  UINT32 pbContextNdrPtr = 0;
3379 
3380  if (!smartcard_ndr_pointer_read(s, &index, &mszNdrPtr))
3381  return ERROR_INVALID_DATA;
3382 
3383  LONG status = smartcard_unpack_redir_scard_context(s, &(call->Common.handles.hContext), &index,
3384  &pbContextNdrPtr);
3385  if (status != SCARD_S_SUCCESS)
3386  return status;
3387 
3388  if (!smartcard_ndr_pointer_read(s, &index, &contextNdrPtr))
3389  return ERROR_INVALID_DATA;
3390 
3391  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
3392  return STATUS_BUFFER_TOO_SMALL;
3393 
3394  Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3395  Stream_Read_UINT32(s, call->Common.cbDataLen);
3396 
3397  if (!smartcard_ndr_pointer_read(s, &index, &pbDataNdrPtr))
3398  return ERROR_INVALID_DATA;
3399 
3400  call->szLookupName = NULL;
3401  if (mszNdrPtr)
3402  {
3403  status = smartcard_ndr_read_a(s, &call->szLookupName, NDR_PTR_FULL);
3404  if (status != SCARD_S_SUCCESS)
3405  return status;
3406  }
3407 
3408  status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
3409  &call->Common.handles.hContext);
3410  if (status != SCARD_S_SUCCESS)
3411  return status;
3412 
3413  call->Common.CardIdentifier = NULL;
3414  if (contextNdrPtr)
3415  {
3416  status = smartcard_ndr_read_u(s, &call->Common.CardIdentifier);
3417  if (status != SCARD_S_SUCCESS)
3418  return status;
3419  }
3420 
3421  call->Common.pbData = NULL;
3422  if (pbDataNdrPtr)
3423  {
3424  status =
3425  smartcard_ndr_read(s, &call->Common.pbData, call->Common.cbDataLen, 1, NDR_PTR_SIMPLE);
3426  if (status != SCARD_S_SUCCESS)
3427  return status;
3428  }
3429  smartcard_trace_write_cache_a_call(call);
3430  return SCARD_S_SUCCESS;
3431 }
3432 
3433 LONG smartcard_unpack_write_cache_w_call(wStream* s, WriteCacheW_Call* call)
3434 {
3435  UINT32 mszNdrPtr = 0;
3436  UINT32 contextNdrPtr = 0;
3437  UINT32 pbDataNdrPtr = 0;
3438  UINT32 index = 0;
3439  UINT32 pbContextNdrPtr = 0;
3440 
3441  if (!smartcard_ndr_pointer_read(s, &index, &mszNdrPtr))
3442  return ERROR_INVALID_DATA;
3443 
3444  LONG status = smartcard_unpack_redir_scard_context(s, &(call->Common.handles.hContext), &index,
3445  &pbContextNdrPtr);
3446  if (status != SCARD_S_SUCCESS)
3447  return status;
3448 
3449  if (!smartcard_ndr_pointer_read(s, &index, &contextNdrPtr))
3450  return ERROR_INVALID_DATA;
3451 
3452  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
3453  return STATUS_BUFFER_TOO_SMALL;
3454  Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3455  Stream_Read_UINT32(s, call->Common.cbDataLen);
3456 
3457  if (!smartcard_ndr_pointer_read(s, &index, &pbDataNdrPtr))
3458  return ERROR_INVALID_DATA;
3459 
3460  call->szLookupName = NULL;
3461  if (mszNdrPtr)
3462  {
3463  status = smartcard_ndr_read_w(s, &call->szLookupName, NDR_PTR_FULL);
3464  if (status != SCARD_S_SUCCESS)
3465  return status;
3466  }
3467 
3468  status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
3469  &call->Common.handles.hContext);
3470  if (status != SCARD_S_SUCCESS)
3471  return status;
3472 
3473  call->Common.CardIdentifier = NULL;
3474  if (contextNdrPtr)
3475  {
3476  status = smartcard_ndr_read_u(s, &call->Common.CardIdentifier);
3477  if (status != SCARD_S_SUCCESS)
3478  return status;
3479  }
3480 
3481  call->Common.pbData = NULL;
3482  if (pbDataNdrPtr)
3483  {
3484  status =
3485  smartcard_ndr_read(s, &call->Common.pbData, call->Common.cbDataLen, 1, NDR_PTR_SIMPLE);
3486  if (status != SCARD_S_SUCCESS)
3487  return status;
3488  }
3489  smartcard_trace_write_cache_w_call(call);
3490  return status;
3491 }
3492 
3493 LONG smartcard_unpack_get_transmit_count_call(wStream* s, GetTransmitCount_Call* call)
3494 {
3495  UINT32 index = 0;
3496  UINT32 pbContextNdrPtr = 0;
3497 
3498  LONG status = smartcard_unpack_redir_scard_context(s, &(call->handles.hContext), &index,
3499  &pbContextNdrPtr);
3500  if (status != SCARD_S_SUCCESS)
3501  return status;
3502 
3503  status = smartcard_unpack_redir_scard_handle(s, &(call->handles.hCard), &index);
3504  if (status != SCARD_S_SUCCESS)
3505  return status;
3506 
3507  if ((status = smartcard_unpack_redir_scard_context_ref(s, pbContextNdrPtr,
3508  &(call->handles.hContext))))
3509  {
3510  WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
3511  status);
3512  return status;
3513  }
3514 
3515  if ((status = smartcard_unpack_redir_scard_handle_ref(s, &(call->handles.hCard))))
3516  WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "",
3517  status);
3518 
3519  smartcard_trace_get_transmit_count_call(call);
3520  return status;
3521 }
3522 
3523 LONG smartcard_unpack_get_reader_icon_call(wStream* s, GetReaderIcon_Call* call)
3524 {
3525  return smartcard_unpack_common_context_and_string_w(s, &call->handles.hContext,
3526  &call->szReaderName);
3527 }
3528 
3529 LONG smartcard_unpack_context_and_string_a_call(wStream* s, ContextAndStringA_Call* call)
3530 {
3531  return smartcard_unpack_common_context_and_string_a(s, &call->handles.hContext, &call->sz);
3532 }
3533 
3534 LONG smartcard_unpack_context_and_string_w_call(wStream* s, ContextAndStringW_Call* call)
3535 {
3536  return smartcard_unpack_common_context_and_string_w(s, &call->handles.hContext, &call->sz);
3537 }
3538 
3539 LONG smartcard_unpack_get_device_type_id_call(wStream* s, GetDeviceTypeId_Call* call)
3540 {
3541  return smartcard_unpack_common_context_and_string_w(s, &call->handles.hContext,
3542  &call->szReaderName);
3543 }
3544 
3545 LONG smartcard_pack_device_type_id_return(wStream* s, const GetDeviceTypeId_Return* ret)
3546 {
3547  smartcard_trace_device_type_id_return(ret);
3548 
3549  if (!Stream_EnsureRemainingCapacity(s, 4))
3550  {
3551  WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
3552  return SCARD_F_INTERNAL_ERROR;
3553  }
3554 
3555  Stream_Write_UINT32(s, ret->dwDeviceId); /* cBytes (4 bytes) */
3556 
3557  return ret->ReturnCode;
3558 }
3559 
3560 LONG smartcard_pack_locate_cards_return(wStream* s, const LocateCards_Return* ret)
3561 {
3562  LONG status = 0;
3563  DWORD cbDataLen = ret->cReaders;
3564  UINT32 index = 0;
3565 
3566  smartcard_trace_locate_cards_return(ret);
3567  if (ret->ReturnCode != SCARD_S_SUCCESS)
3568  cbDataLen = 0;
3569  if (cbDataLen == SCARD_AUTOALLOCATE)
3570  cbDataLen = 0;
3571 
3572  if (!Stream_EnsureRemainingCapacity(s, 4))
3573  {
3574  WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
3575  return SCARD_F_INTERNAL_ERROR;
3576  }
3577 
3578  Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
3579  if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3580  return SCARD_E_NO_MEMORY;
3581 
3582  status = smartcard_ndr_write_state(s, ret->rgReaderStates, cbDataLen, NDR_PTR_SIMPLE);
3583  if (status != SCARD_S_SUCCESS)
3584  return status;
3585  return ret->ReturnCode;
3586 }
3587 
3588 LONG smartcard_pack_get_reader_icon_return(wStream* s, const GetReaderIcon_Return* ret)
3589 {
3590  LONG status = 0;
3591  UINT32 index = 0;
3592  DWORD cbDataLen = ret->cbDataLen;
3593  smartcard_trace_get_reader_icon_return(ret);
3594  if (ret->ReturnCode != SCARD_S_SUCCESS)
3595  cbDataLen = 0;
3596  if (cbDataLen == SCARD_AUTOALLOCATE)
3597  cbDataLen = 0;
3598 
3599  if (!Stream_EnsureRemainingCapacity(s, 4))
3600  {
3601  WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
3602  return SCARD_F_INTERNAL_ERROR;
3603  }
3604 
3605  Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
3606  if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3607  return SCARD_E_NO_MEMORY;
3608 
3609  status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
3610  if (status != SCARD_S_SUCCESS)
3611  return status;
3612  return ret->ReturnCode;
3613 }
3614 
3615 LONG smartcard_pack_get_transmit_count_return(wStream* s, const GetTransmitCount_Return* ret)
3616 {
3617  smartcard_trace_get_transmit_count_return(ret);
3618 
3619  if (!Stream_EnsureRemainingCapacity(s, 4))
3620  {
3621  WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
3622  return SCARD_F_INTERNAL_ERROR;
3623  }
3624 
3625  Stream_Write_UINT32(s, ret->cTransmitCount); /* cBytes (4 cbDataLen) */
3626 
3627  return ret->ReturnCode;
3628 }
3629 
3630 LONG smartcard_pack_read_cache_return(wStream* s, const ReadCache_Return* ret)
3631 {
3632  LONG status = 0;
3633  UINT32 index = 0;
3634  DWORD cbDataLen = ret->cbDataLen;
3635  smartcard_trace_read_cache_return(ret);
3636  if (ret->ReturnCode != SCARD_S_SUCCESS)
3637  cbDataLen = 0;
3638 
3639  if (cbDataLen == SCARD_AUTOALLOCATE)
3640  cbDataLen = 0;
3641 
3642  if (!Stream_EnsureRemainingCapacity(s, 4))
3643  {
3644  WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
3645  return SCARD_F_INTERNAL_ERROR;
3646  }
3647 
3648  Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
3649  if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3650  return SCARD_E_NO_MEMORY;
3651 
3652  status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
3653  if (status != SCARD_S_SUCCESS)
3654  return status;
3655  return ret->ReturnCode;
3656 }
Definition: wtypes.h:252