FreeRDP
smartcard_call.c
1 
26 #include <freerdp/config.h>
27 
28 #include <winpr/assert.h>
29 
30 #include <winpr/crt.h>
31 #include <winpr/print.h>
32 #include <winpr/stream.h>
33 #include <winpr/library.h>
34 #include <winpr/smartcard.h>
35 
36 #include <freerdp/freerdp.h>
37 #include <freerdp/channels/rdpdr.h>
38 #include <freerdp/channels/scard.h>
39 
40 #include <freerdp/utils/rdpdr_utils.h>
41 #include <freerdp/utils/smartcard_pack.h>
42 #include <freerdp/utils/smartcard_call.h>
43 
44 #include <freerdp/log.h>
45 #define TAG FREERDP_TAG("utils.smartcard.call")
46 
47 #if defined(WITH_SMARTCARD_EMULATE)
48 #include <freerdp/emulate/scard/smartcard_emulate.h>
49 
50 #define wrap(ctx, fkt, ...) \
51  ctx->useEmulatedCard ? Emulate_##fkt(ctx->emulation, ##__VA_ARGS__) \
52  : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
53 #define wrap_ptr(ctx, fkt, ...) wrap(ctx, fkt, ##__VA_ARGS__)
54 #else
55 #define wrap(ctx, fkt, ...) \
56  ctx->useEmulatedCard ? SCARD_F_INTERNAL_ERROR : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
57 #define wrap_ptr(ctx, fkt, ...) \
58  ctx->useEmulatedCard ? NULL : ctx->pWinSCardApi->pfn##fkt(__VA_ARGS__)
59 #endif
60 
61 struct s_scard_call_context
62 {
63  BOOL useEmulatedCard;
64  HANDLE StartedEvent;
65  wLinkedList* names;
66  wHashTable* rgSCardContextList;
67 #if defined(WITH_SMARTCARD_EMULATE)
68  SmartcardEmulationContext* emulation;
69 #endif
70  HANDLE hWinSCardLibrary;
71  SCardApiFunctionTable WinSCardApi;
72  const SCardApiFunctionTable* pWinSCardApi;
73  HANDLE stopEvent;
74  void* userdata;
75 
76  void* (*fn_new)(void*, SCARDCONTEXT);
77  void (*fn_free)(void*);
78 };
79 
80 struct s_scard_context_element
81 {
82  void* context;
83  void (*fn_free)(void*);
84 };
85 
86 static void context_free(void* arg);
87 
88 static LONG smartcard_EstablishContext_Call(scard_call_context* smartcard, wStream* out,
89  SMARTCARD_OPERATION* operation)
90 {
91  LONG status = 0;
92  SCARDCONTEXT hContext = { 0 };
93  EstablishContext_Return ret = { 0 };
94  EstablishContext_Call* call = &operation->call.establishContext;
95  status = ret.ReturnCode =
96  wrap(smartcard, SCardEstablishContext, call->dwScope, NULL, NULL, &hContext);
97 
98  if (ret.ReturnCode == SCARD_S_SUCCESS)
99  {
100  const void* key = (void*)(size_t)hContext;
101  struct s_scard_context_element* pContext =
102  calloc(1, sizeof(struct s_scard_context_element));
103  if (!pContext)
104  return STATUS_NO_MEMORY;
105 
106  pContext->fn_free = smartcard->fn_free;
107 
108  if (smartcard->fn_new)
109  {
110  pContext->context = smartcard->fn_new(smartcard->userdata, hContext);
111  if (!pContext->context)
112  {
113  free(pContext);
114  return STATUS_NO_MEMORY;
115  }
116  }
117 
118  if (!HashTable_Insert(smartcard->rgSCardContextList, key, (void*)pContext))
119  {
120  WLog_ERR(TAG, "ListDictionary_Add failed!");
121  context_free(pContext);
122  return STATUS_INTERNAL_ERROR;
123  }
124  }
125  else
126  {
127  return scard_log_status_error(TAG, "SCardEstablishContext", status);
128  }
129 
130  // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): HashTable_Insert takes ownership of pContext
131  smartcard_scard_context_native_to_redir(&(ret.hContext), hContext);
132 
133  status = smartcard_pack_establish_context_return(out, &ret);
134  if (status != SCARD_S_SUCCESS)
135  {
136  return scard_log_status_error(TAG, "smartcard_pack_establish_context_return", status);
137  }
138 
139  return ret.ReturnCode;
140 }
141 
142 static LONG smartcard_ReleaseContext_Call(scard_call_context* smartcard, wStream* out,
143  SMARTCARD_OPERATION* operation)
144 {
145  Long_Return ret = { 0 };
146 
147  WINPR_ASSERT(smartcard);
148  WINPR_ASSERT(out);
149  WINPR_ASSERT(operation);
150 
151  ret.ReturnCode = wrap(smartcard, SCardReleaseContext, operation->hContext);
152 
153  if (ret.ReturnCode == SCARD_S_SUCCESS)
154  HashTable_Remove(smartcard->rgSCardContextList, (void*)operation->hContext);
155  else
156  {
157  return scard_log_status_error(TAG, "SCardReleaseContext", ret.ReturnCode);
158  }
159 
160  smartcard_trace_long_return(&ret, "ReleaseContext");
161  return ret.ReturnCode;
162 }
163 
164 static LONG smartcard_IsValidContext_Call(scard_call_context* smartcard, wStream* out,
165  SMARTCARD_OPERATION* operation)
166 {
167  Long_Return ret = { 0 };
168 
169  WINPR_ASSERT(smartcard);
170  WINPR_ASSERT(out);
171  WINPR_ASSERT(operation);
172 
173  ret.ReturnCode = wrap(smartcard, SCardIsValidContext, operation->hContext);
174  smartcard_trace_long_return(&ret, "IsValidContext");
175  return ret.ReturnCode;
176 }
177 
178 static LONG smartcard_ListReaderGroupsA_Call(scard_call_context* smartcard, wStream* out,
179  SMARTCARD_OPERATION* operation)
180 {
181  LONG status = 0;
182  ListReaderGroups_Return ret = { 0 };
183  LPSTR mszGroups = NULL;
184  DWORD cchGroups = 0;
185 
186  WINPR_ASSERT(smartcard);
187  WINPR_ASSERT(out);
188  WINPR_ASSERT(operation);
189 
190  cchGroups = SCARD_AUTOALLOCATE;
191  ret.ReturnCode =
192  wrap(smartcard, SCardListReaderGroupsA, operation->hContext, (LPSTR)&mszGroups, &cchGroups);
193  if (cchGroups == SCARD_AUTOALLOCATE)
194  return SCARD_F_UNKNOWN_ERROR;
195 
196  ret.msz = (BYTE*)mszGroups;
197  ret.cBytes = cchGroups;
198 
199  status = smartcard_pack_list_reader_groups_return(out, &ret, FALSE);
200 
201  if (status != SCARD_S_SUCCESS)
202  return status;
203 
204  if (mszGroups)
205  wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
206 
207  return ret.ReturnCode;
208 }
209 
210 static LONG smartcard_ListReaderGroupsW_Call(scard_call_context* smartcard, wStream* out,
211  SMARTCARD_OPERATION* operation)
212 {
213  LONG status = 0;
214  ListReaderGroups_Return ret = { 0 };
215  LPWSTR mszGroups = NULL;
216  DWORD cchGroups = 0;
217 
218  WINPR_ASSERT(smartcard);
219  WINPR_ASSERT(out);
220  WINPR_ASSERT(operation);
221 
222  cchGroups = SCARD_AUTOALLOCATE;
223  status = ret.ReturnCode = wrap(smartcard, SCardListReaderGroupsW, operation->hContext,
224  (LPWSTR)&mszGroups, &cchGroups);
225  if (cchGroups == SCARD_AUTOALLOCATE)
226  return SCARD_F_UNKNOWN_ERROR;
227 
228  ret.msz = (BYTE*)mszGroups;
229 
230  WINPR_ASSERT(cchGroups < SCARD_AUTOALLOCATE / sizeof(WCHAR));
231  const size_t blen = sizeof(WCHAR) * cchGroups;
232  WINPR_ASSERT(blen <= UINT32_MAX);
233  ret.cBytes = (UINT32)blen;
234 
235  if (status != SCARD_S_SUCCESS)
236  return status;
237 
238  status = smartcard_pack_list_reader_groups_return(out, &ret, TRUE);
239 
240  if (status != SCARD_S_SUCCESS)
241  return status;
242 
243  if (mszGroups)
244  wrap(smartcard, SCardFreeMemory, operation->hContext, mszGroups);
245 
246  return ret.ReturnCode;
247 }
248 
249 static BOOL filter_match(wLinkedList* list, LPCSTR reader, size_t readerLen)
250 {
251  if (readerLen < 1)
252  return FALSE;
253 
254  LinkedList_Enumerator_Reset(list);
255 
256  while (LinkedList_Enumerator_MoveNext(list))
257  {
258  const char* filter = LinkedList_Enumerator_Current(list);
259 
260  if (filter)
261  {
262  if (strstr(reader, filter) != NULL)
263  return TRUE;
264  }
265  }
266 
267  return FALSE;
268 }
269 
270 static DWORD filter_device_by_name_a(wLinkedList* list, LPSTR* mszReaders, DWORD cchReaders)
271 {
272  size_t rpos = 0;
273  size_t wpos = 0;
274 
275  if (*mszReaders == NULL || LinkedList_Count(list) < 1)
276  return cchReaders;
277 
278  do
279  {
280  LPCSTR rreader = &(*mszReaders)[rpos];
281  LPSTR wreader = &(*mszReaders)[wpos];
282  size_t readerLen = strnlen(rreader, cchReaders - rpos);
283 
284  rpos += readerLen + 1;
285 
286  if (filter_match(list, rreader, readerLen))
287  {
288  if (rreader != wreader)
289  memmove(wreader, rreader, readerLen + 1);
290 
291  wpos += readerLen + 1;
292  }
293  } while (rpos < cchReaders);
294 
295  /* this string must be double 0 terminated */
296  if (rpos != wpos)
297  {
298  if (wpos >= cchReaders)
299  return 0;
300 
301  (*mszReaders)[wpos++] = '\0';
302  }
303 
304  return (DWORD)wpos;
305 }
306 
307 static DWORD filter_device_by_name_w(wLinkedList* list, LPWSTR* mszReaders, DWORD cchReaders)
308 {
309  DWORD rc = 0;
310  LPSTR readers = NULL;
311 
312  if (LinkedList_Count(list) < 1)
313  return cchReaders;
314 
315  readers = ConvertMszWCharNToUtf8Alloc(*mszReaders, cchReaders, NULL);
316 
317  if (!readers)
318  {
319  free(readers);
320  return 0;
321  }
322 
323  free(*mszReaders);
324  *mszReaders = NULL;
325  rc = filter_device_by_name_a(list, &readers, cchReaders);
326 
327  *mszReaders = ConvertMszUtf8NToWCharAlloc(readers, rc, NULL);
328  if (!*mszReaders)
329  rc = 0;
330 
331  free(readers);
332  return rc;
333 }
334 
335 static LONG smartcard_ListReadersA_Call(scard_call_context* smartcard, wStream* out,
336  SMARTCARD_OPERATION* operation)
337 {
338  ListReaders_Return ret = { 0 };
339  LPSTR mszReaders = NULL;
340 
341  WINPR_ASSERT(smartcard);
342  WINPR_ASSERT(out);
343  WINPR_ASSERT(operation);
344 
345  ListReaders_Call* call = &operation->call.listReaders;
346  DWORD cchReaders = SCARD_AUTOALLOCATE;
347  LONG status = ret.ReturnCode = wrap(smartcard, SCardListReadersA, operation->hContext,
348  (LPCSTR)call->mszGroups, (LPSTR)&mszReaders, &cchReaders);
349  if (cchReaders == SCARD_AUTOALLOCATE)
350  return SCARD_F_UNKNOWN_ERROR;
351 
352  if (status != SCARD_S_SUCCESS)
353  return scard_log_status_error(TAG, "SCardListReadersA", status);
354 
355  cchReaders = filter_device_by_name_a(smartcard->names, &mszReaders, cchReaders);
356  ret.msz = (BYTE*)mszReaders;
357  ret.cBytes = cchReaders;
358 
359  status = smartcard_pack_list_readers_return(out, &ret, FALSE);
360  if (mszReaders)
361  wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaders);
362 
363  if (status != SCARD_S_SUCCESS)
364  return scard_log_status_error(TAG, "smartcard_pack_list_readers_return", status);
365 
366  return ret.ReturnCode;
367 }
368 
369 static LONG smartcard_ListReadersW_Call(scard_call_context* smartcard, wStream* out,
370  SMARTCARD_OPERATION* operation)
371 {
372  LONG status = 0;
373  ListReaders_Return ret = { 0 };
374  DWORD cchReaders = 0;
375  ListReaders_Call* call = NULL;
376  union
377  {
378  const BYTE* bp;
379  const char* sz;
380  const WCHAR* wz;
381  } string;
382  union
383  {
384  WCHAR** ppw;
385  WCHAR* pw;
386  CHAR* pc;
387  BYTE* pb;
388  } mszReaders;
389 
390  WINPR_ASSERT(smartcard);
391  WINPR_ASSERT(operation);
392 
393  call = &operation->call.listReaders;
394 
395  string.bp = call->mszGroups;
396  cchReaders = SCARD_AUTOALLOCATE;
397  status = ret.ReturnCode = wrap(smartcard, SCardListReadersW, operation->hContext, string.wz,
398  (LPWSTR)&mszReaders.pw, &cchReaders);
399  if (cchReaders == SCARD_AUTOALLOCATE)
400  return SCARD_F_UNKNOWN_ERROR;
401 
402  if (status != SCARD_S_SUCCESS)
403  return scard_log_status_error(TAG, "SCardListReadersW", status);
404 
405  cchReaders = filter_device_by_name_w(smartcard->names, &mszReaders.pw, cchReaders);
406  ret.msz = mszReaders.pb;
407  ret.cBytes = cchReaders * sizeof(WCHAR);
408  status = smartcard_pack_list_readers_return(out, &ret, TRUE);
409 
410  if (mszReaders.pb)
411  wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaders.pb);
412 
413  if (status != SCARD_S_SUCCESS)
414  return status;
415 
416  return ret.ReturnCode;
417 }
418 
419 static LONG smartcard_IntroduceReaderGroupA_Call(scard_call_context* smartcard, wStream* out,
420  SMARTCARD_OPERATION* operation)
421 {
422  Long_Return ret = { 0 };
423  ContextAndStringA_Call* call = NULL;
424 
425  WINPR_ASSERT(smartcard);
426  WINPR_ASSERT(out);
427  WINPR_ASSERT(operation);
428 
429  call = &operation->call.contextAndStringA;
430  ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupA, operation->hContext, call->sz);
431  scard_log_status_error(TAG, "SCardIntroduceReaderGroupA", ret.ReturnCode);
432  smartcard_trace_long_return(&ret, "IntroduceReaderGroupA");
433  return ret.ReturnCode;
434 }
435 
436 static LONG smartcard_IntroduceReaderGroupW_Call(scard_call_context* smartcard, wStream* out,
437  SMARTCARD_OPERATION* operation)
438 {
439  Long_Return ret = { 0 };
440  ContextAndStringW_Call* call = NULL;
441 
442  WINPR_ASSERT(smartcard);
443  WINPR_ASSERT(out);
444  WINPR_ASSERT(operation);
445 
446  call = &operation->call.contextAndStringW;
447  ret.ReturnCode = wrap(smartcard, SCardIntroduceReaderGroupW, operation->hContext, call->sz);
448  scard_log_status_error(TAG, "SCardIntroduceReaderGroupW", ret.ReturnCode);
449  smartcard_trace_long_return(&ret, "IntroduceReaderGroupW");
450  return ret.ReturnCode;
451 }
452 
453 static LONG smartcard_IntroduceReaderA_Call(scard_call_context* smartcard, wStream* out,
454  SMARTCARD_OPERATION* operation)
455 {
456  Long_Return ret = { 0 };
457  ContextAndTwoStringA_Call* call = NULL;
458 
459  WINPR_ASSERT(smartcard);
460  WINPR_ASSERT(out);
461  WINPR_ASSERT(operation);
462 
463  call = &operation->call.contextAndTwoStringA;
464  ret.ReturnCode =
465  wrap(smartcard, SCardIntroduceReaderA, operation->hContext, call->sz1, call->sz2);
466  scard_log_status_error(TAG, "SCardIntroduceReaderA", ret.ReturnCode);
467  smartcard_trace_long_return(&ret, "IntroduceReaderA");
468  return ret.ReturnCode;
469 }
470 
471 static LONG smartcard_IntroduceReaderW_Call(scard_call_context* smartcard, wStream* out,
472  SMARTCARD_OPERATION* operation)
473 {
474  Long_Return ret = { 0 };
475  ContextAndTwoStringW_Call* call = NULL;
476 
477  WINPR_ASSERT(smartcard);
478  WINPR_ASSERT(out);
479  WINPR_ASSERT(operation);
480 
481  call = &operation->call.contextAndTwoStringW;
482  ret.ReturnCode =
483  wrap(smartcard, SCardIntroduceReaderW, operation->hContext, call->sz1, call->sz2);
484  scard_log_status_error(TAG, "SCardIntroduceReaderW", ret.ReturnCode);
485  smartcard_trace_long_return(&ret, "IntroduceReaderW");
486  return ret.ReturnCode;
487 }
488 
489 static LONG smartcard_ForgetReaderA_Call(scard_call_context* smartcard, wStream* out,
490  SMARTCARD_OPERATION* operation)
491 {
492  Long_Return ret = { 0 };
493  ContextAndStringA_Call* call = NULL;
494 
495  WINPR_ASSERT(smartcard);
496  WINPR_ASSERT(out);
497  WINPR_ASSERT(operation);
498 
499  call = &operation->call.contextAndStringA;
500  ret.ReturnCode = wrap(smartcard, SCardForgetReaderA, operation->hContext, call->sz);
501  scard_log_status_error(TAG, "SCardForgetReaderA", ret.ReturnCode);
502  smartcard_trace_long_return(&ret, "SCardForgetReaderA");
503  return ret.ReturnCode;
504 }
505 
506 static LONG smartcard_ForgetReaderW_Call(scard_call_context* smartcard, wStream* out,
507  SMARTCARD_OPERATION* operation)
508 {
509  Long_Return ret = { 0 };
510  ContextAndStringW_Call* call = NULL;
511 
512  WINPR_ASSERT(smartcard);
513  WINPR_ASSERT(out);
514  WINPR_ASSERT(operation);
515 
516  call = &operation->call.contextAndStringW;
517  ret.ReturnCode = wrap(smartcard, SCardForgetReaderW, operation->hContext, call->sz);
518  scard_log_status_error(TAG, "SCardForgetReaderW", ret.ReturnCode);
519  smartcard_trace_long_return(&ret, "SCardForgetReaderW");
520  return ret.ReturnCode;
521 }
522 
523 static LONG smartcard_AddReaderToGroupA_Call(scard_call_context* smartcard, wStream* out,
524  SMARTCARD_OPERATION* operation)
525 {
526  Long_Return ret = { 0 };
527  ContextAndTwoStringA_Call* call = NULL;
528 
529  WINPR_ASSERT(smartcard);
530  WINPR_ASSERT(out);
531  WINPR_ASSERT(operation);
532 
533  call = &operation->call.contextAndTwoStringA;
534  ret.ReturnCode =
535  wrap(smartcard, SCardAddReaderToGroupA, operation->hContext, call->sz1, call->sz2);
536  scard_log_status_error(TAG, "SCardAddReaderToGroupA", ret.ReturnCode);
537  smartcard_trace_long_return(&ret, "SCardAddReaderToGroupA");
538  return ret.ReturnCode;
539 }
540 
541 static LONG smartcard_AddReaderToGroupW_Call(scard_call_context* smartcard, wStream* out,
542  SMARTCARD_OPERATION* operation)
543 {
544  Long_Return ret = { 0 };
545  ContextAndTwoStringW_Call* call = NULL;
546 
547  WINPR_ASSERT(smartcard);
548  WINPR_ASSERT(out);
549  WINPR_ASSERT(operation);
550 
551  call = &operation->call.contextAndTwoStringW;
552  ret.ReturnCode =
553  wrap(smartcard, SCardAddReaderToGroupW, operation->hContext, call->sz1, call->sz2);
554  scard_log_status_error(TAG, "SCardAddReaderToGroupW", ret.ReturnCode);
555  smartcard_trace_long_return(&ret, "SCardAddReaderToGroupA");
556  return ret.ReturnCode;
557 }
558 
559 static LONG smartcard_RemoveReaderFromGroupA_Call(scard_call_context* smartcard, wStream* out,
560  SMARTCARD_OPERATION* operation)
561 {
562  Long_Return ret = { 0 };
563  ContextAndTwoStringA_Call* call = NULL;
564 
565  WINPR_ASSERT(smartcard);
566  WINPR_ASSERT(out);
567  WINPR_ASSERT(operation);
568 
569  call = &operation->call.contextAndTwoStringA;
570  ret.ReturnCode =
571  wrap(smartcard, SCardRemoveReaderFromGroupA, operation->hContext, call->sz1, call->sz2);
572  scard_log_status_error(TAG, "SCardRemoveReaderFromGroupA", ret.ReturnCode);
573  smartcard_trace_long_return(&ret, "SCardRemoveReaderFromGroupA");
574  return ret.ReturnCode;
575 }
576 
577 static LONG smartcard_RemoveReaderFromGroupW_Call(scard_call_context* smartcard, wStream* out,
578  SMARTCARD_OPERATION* operation)
579 {
580  Long_Return ret = { 0 };
581  ContextAndTwoStringW_Call* call = NULL;
582 
583  WINPR_ASSERT(smartcard);
584  WINPR_ASSERT(out);
585  WINPR_ASSERT(operation);
586 
587  call = &operation->call.contextAndTwoStringW;
588  ret.ReturnCode =
589  wrap(smartcard, SCardRemoveReaderFromGroupW, operation->hContext, call->sz1, call->sz2);
590  scard_log_status_error(TAG, "SCardRemoveReaderFromGroupW", ret.ReturnCode);
591  smartcard_trace_long_return(&ret, "SCardRemoveReaderFromGroupW");
592  return ret.ReturnCode;
593 }
594 
595 static LONG smartcard_LocateCardsA_Call(scard_call_context* smartcard, wStream* out,
596  SMARTCARD_OPERATION* operation)
597 {
598  LONG status = 0;
599  LocateCards_Return ret = { 0 };
600  LocateCardsA_Call* call = NULL;
601 
602  WINPR_ASSERT(smartcard);
603  WINPR_ASSERT(operation);
604 
605  call = &operation->call.locateCardsA;
606 
607  ret.ReturnCode = wrap(smartcard, SCardLocateCardsA, operation->hContext, call->mszCards,
608  call->rgReaderStates, call->cReaders);
609  scard_log_status_error(TAG, "SCardLocateCardsA", ret.ReturnCode);
610  ret.cReaders = call->cReaders;
611  ret.rgReaderStates = NULL;
612 
613  if (ret.cReaders > 0)
614  {
615  ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return));
616 
617  if (!ret.rgReaderStates)
618  return STATUS_NO_MEMORY;
619  }
620 
621  for (UINT32 x = 0; x < ret.cReaders; x++)
622  {
623  ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
624  ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
625  ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
626  CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
627  sizeof(ret.rgReaderStates[x].rgbAtr));
628  }
629 
630  status = smartcard_pack_locate_cards_return(out, &ret);
631 
632  if (status != SCARD_S_SUCCESS)
633  return status;
634 
635  return ret.ReturnCode;
636 }
637 
638 static LONG smartcard_LocateCardsW_Call(scard_call_context* smartcard, wStream* out,
639  SMARTCARD_OPERATION* operation)
640 {
641  LONG status = 0;
642  LocateCards_Return ret = { 0 };
643  LocateCardsW_Call* call = NULL;
644 
645  WINPR_ASSERT(smartcard);
646  WINPR_ASSERT(operation);
647 
648  call = &operation->call.locateCardsW;
649 
650  ret.ReturnCode = wrap(smartcard, SCardLocateCardsW, operation->hContext, call->mszCards,
651  call->rgReaderStates, call->cReaders);
652  scard_log_status_error(TAG, "SCardLocateCardsW", ret.ReturnCode);
653  ret.cReaders = call->cReaders;
654  ret.rgReaderStates = NULL;
655 
656  if (ret.cReaders > 0)
657  {
658  ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return));
659 
660  if (!ret.rgReaderStates)
661  return STATUS_NO_MEMORY;
662  }
663 
664  for (UINT32 x = 0; x < ret.cReaders; x++)
665  {
666  ret.rgReaderStates[x].dwCurrentState = call->rgReaderStates[x].dwCurrentState;
667  ret.rgReaderStates[x].dwEventState = call->rgReaderStates[x].dwEventState;
668  ret.rgReaderStates[x].cbAtr = call->rgReaderStates[x].cbAtr;
669  CopyMemory(&(ret.rgReaderStates[x].rgbAtr), &(call->rgReaderStates[x].rgbAtr),
670  sizeof(ret.rgReaderStates[x].rgbAtr));
671  }
672 
673  status = smartcard_pack_locate_cards_return(out, &ret);
674 
675  if (status != SCARD_S_SUCCESS)
676  return status;
677 
678  return ret.ReturnCode;
679 }
680 
681 static LONG smartcard_ReadCacheA_Call(scard_call_context* smartcard, wStream* out,
682  SMARTCARD_OPERATION* operation)
683 {
684  LONG status = 0;
685  BOOL autoalloc = 0;
686  ReadCache_Return ret = { 0 };
687  ReadCacheA_Call* call = NULL;
688 
689  WINPR_ASSERT(smartcard);
690  WINPR_ASSERT(out);
691  WINPR_ASSERT(operation);
692 
693  call = &operation->call.readCacheA;
694  autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE);
695 
696  if (!call->Common.fPbDataIsNULL)
697  {
698  ret.cbDataLen = call->Common.cbDataLen;
699  if (!autoalloc)
700  {
701  ret.pbData = malloc(ret.cbDataLen);
702  if (!ret.pbData)
703  return SCARD_F_INTERNAL_ERROR;
704  }
705  }
706 
707  if (autoalloc)
708  ret.ReturnCode = wrap(smartcard, SCardReadCacheA, operation->hContext,
709  call->Common.CardIdentifier, call->Common.FreshnessCounter,
710  call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
711  else
712  ret.ReturnCode =
713  wrap(smartcard, SCardReadCacheA, operation->hContext, call->Common.CardIdentifier,
714  call->Common.FreshnessCounter, call->szLookupName, ret.pbData, &ret.cbDataLen);
715  if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
716  (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
717  {
718  scard_log_status_error(TAG, "SCardReadCacheA", ret.ReturnCode);
719  }
720 
721  status = smartcard_pack_read_cache_return(out, &ret);
722  if (autoalloc)
723  wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
724  else
725  free(ret.pbData);
726  if (status != SCARD_S_SUCCESS)
727  return status;
728 
729  return ret.ReturnCode;
730 }
731 
732 static LONG smartcard_ReadCacheW_Call(scard_call_context* smartcard, wStream* out,
733  SMARTCARD_OPERATION* operation)
734 {
735  LONG status = 0;
736  ReadCache_Return ret = { 0 };
737  ReadCacheW_Call* call = NULL;
738 
739  WINPR_ASSERT(smartcard);
740  WINPR_ASSERT(out);
741  WINPR_ASSERT(operation);
742 
743  call = &operation->call.readCacheW;
744 
745  if (!call->Common.fPbDataIsNULL)
746  ret.cbDataLen = SCARD_AUTOALLOCATE;
747 
748  ret.ReturnCode =
749  wrap(smartcard, SCardReadCacheW, operation->hContext, call->Common.CardIdentifier,
750  call->Common.FreshnessCounter, call->szLookupName, (BYTE*)&ret.pbData, &ret.cbDataLen);
751 
752  if ((ret.ReturnCode != SCARD_W_CACHE_ITEM_NOT_FOUND) &&
753  (ret.ReturnCode != SCARD_W_CACHE_ITEM_STALE))
754  {
755  scard_log_status_error(TAG, "SCardReadCacheW", ret.ReturnCode);
756  }
757 
758  status = smartcard_pack_read_cache_return(out, &ret);
759 
760  wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
761 
762  if (status != SCARD_S_SUCCESS)
763  return status;
764 
765  return ret.ReturnCode;
766 }
767 
768 static LONG smartcard_WriteCacheA_Call(scard_call_context* smartcard, wStream* out,
769  SMARTCARD_OPERATION* operation)
770 {
771  Long_Return ret = { 0 };
772  WriteCacheA_Call* call = NULL;
773 
774  WINPR_ASSERT(smartcard);
775  WINPR_ASSERT(out);
776  WINPR_ASSERT(operation);
777 
778  call = &operation->call.writeCacheA;
779 
780  ret.ReturnCode = wrap(smartcard, SCardWriteCacheA, operation->hContext,
781  call->Common.CardIdentifier, call->Common.FreshnessCounter,
782  call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
783  scard_log_status_error(TAG, "SCardWriteCacheA", ret.ReturnCode);
784  smartcard_trace_long_return(&ret, "SCardWriteCacheA");
785  return ret.ReturnCode;
786 }
787 
788 static LONG smartcard_WriteCacheW_Call(scard_call_context* smartcard, wStream* out,
789  SMARTCARD_OPERATION* operation)
790 {
791  Long_Return ret = { 0 };
792  WriteCacheW_Call* call = NULL;
793 
794  WINPR_ASSERT(smartcard);
795  WINPR_ASSERT(out);
796  WINPR_ASSERT(operation);
797 
798  call = &operation->call.writeCacheW;
799 
800  ret.ReturnCode = wrap(smartcard, SCardWriteCacheW, operation->hContext,
801  call->Common.CardIdentifier, call->Common.FreshnessCounter,
802  call->szLookupName, call->Common.pbData, call->Common.cbDataLen);
803  scard_log_status_error(TAG, "SCardWriteCacheW", ret.ReturnCode);
804  smartcard_trace_long_return(&ret, "SCardWriteCacheW");
805  return ret.ReturnCode;
806 }
807 
808 static LONG smartcard_GetTransmitCount_Call(scard_call_context* smartcard, wStream* out,
809  SMARTCARD_OPERATION* operation)
810 {
811  LONG status = 0;
812  GetTransmitCount_Return ret = { 0 };
813 
814  WINPR_ASSERT(smartcard);
815  WINPR_ASSERT(out);
816  WINPR_ASSERT(operation);
817 
818  ret.ReturnCode = wrap(smartcard, SCardGetTransmitCount, operation->hCard, &ret.cTransmitCount);
819  scard_log_status_error(TAG, "SCardGetTransmitCount", ret.ReturnCode);
820  status = smartcard_pack_get_transmit_count_return(out, &ret);
821  if (status != SCARD_S_SUCCESS)
822  return status;
823 
824  return ret.ReturnCode;
825 }
826 
827 static LONG smartcard_ReleaseStartedEvent_Call(scard_call_context* smartcard, wStream* out,
828  SMARTCARD_OPERATION* operation)
829 {
830  WINPR_UNUSED(smartcard);
831  WINPR_UNUSED(out);
832  WINPR_UNUSED(operation);
833 
834  WLog_WARN(TAG, "According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
835  "this is not supported?!?");
836  return SCARD_E_UNSUPPORTED_FEATURE;
837 }
838 
839 static LONG smartcard_GetReaderIcon_Call(scard_call_context* smartcard, wStream* out,
840  SMARTCARD_OPERATION* operation)
841 {
842  LONG status = 0;
843  GetReaderIcon_Return ret = { 0 };
844  GetReaderIcon_Call* call = NULL;
845 
846  WINPR_ASSERT(smartcard);
847  WINPR_ASSERT(out);
848  WINPR_ASSERT(operation);
849 
850  call = &operation->call.getReaderIcon;
851 
852  ret.cbDataLen = SCARD_AUTOALLOCATE;
853  ret.ReturnCode = wrap(smartcard, SCardGetReaderIconW, operation->hContext, call->szReaderName,
854  (LPBYTE)&ret.pbData, &ret.cbDataLen);
855  scard_log_status_error(TAG, "SCardGetReaderIconW", ret.ReturnCode);
856  if (ret.cbDataLen == SCARD_AUTOALLOCATE)
857  return SCARD_F_UNKNOWN_ERROR;
858 
859  status = smartcard_pack_get_reader_icon_return(out, &ret);
860  wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbData);
861  if (status != SCARD_S_SUCCESS)
862  return status;
863 
864  return ret.ReturnCode;
865 }
866 
867 static LONG smartcard_GetDeviceTypeId_Call(scard_call_context* smartcard, wStream* out,
868  SMARTCARD_OPERATION* operation)
869 {
870  LONG status = 0;
871  GetDeviceTypeId_Return ret = { 0 };
872  GetDeviceTypeId_Call* call = NULL;
873 
874  WINPR_ASSERT(smartcard);
875  WINPR_ASSERT(out);
876  WINPR_ASSERT(operation);
877 
878  call = &operation->call.getDeviceTypeId;
879 
880  ret.ReturnCode = wrap(smartcard, SCardGetDeviceTypeIdW, operation->hContext, call->szReaderName,
881  &ret.dwDeviceId);
882  scard_log_status_error(TAG, "SCardGetDeviceTypeIdW", ret.ReturnCode);
883 
884  status = smartcard_pack_device_type_id_return(out, &ret);
885  if (status != SCARD_S_SUCCESS)
886  return status;
887 
888  return ret.ReturnCode;
889 }
890 
891 static LONG smartcard_GetStatusChangeA_Call(scard_call_context* smartcard, wStream* out,
892  SMARTCARD_OPERATION* operation)
893 {
894  LONG status = STATUS_NO_MEMORY;
895  DWORD dwTimeOut = 0;
896  const DWORD dwTimeStep = 100;
897  GetStatusChange_Return ret = { 0 };
898  GetStatusChangeA_Call* call = NULL;
899  LPSCARD_READERSTATEA rgReaderStates = NULL;
900 
901  WINPR_ASSERT(smartcard);
902  WINPR_ASSERT(out);
903  WINPR_ASSERT(operation);
904 
905  call = &operation->call.getStatusChangeA;
906  dwTimeOut = call->dwTimeOut;
907 
908  if (call->cReaders > 0)
909  {
910  ret.cReaders = call->cReaders;
911  rgReaderStates = calloc(ret.cReaders, sizeof(SCARD_READERSTATEA));
912  ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return));
913  if (!rgReaderStates || !ret.rgReaderStates)
914  goto fail;
915  }
916 
917  for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
918  {
919  if (call->cReaders > 0)
920  memcpy(rgReaderStates, call->rgReaderStates,
921  call->cReaders * sizeof(SCARD_READERSTATEA));
922  ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
923  MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
924  if (ret.ReturnCode != SCARD_E_TIMEOUT)
925  break;
926  if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
927  break;
928  if (dwTimeOut != INFINITE)
929  x += dwTimeStep;
930  }
931  scard_log_status_error(TAG, "SCardGetStatusChangeA", ret.ReturnCode);
932 
933  for (UINT32 index = 0; index < ret.cReaders; index++)
934  {
935  const SCARD_READERSTATEA* cur = &rgReaderStates[index];
936  ReaderState_Return* rout = &ret.rgReaderStates[index];
937 
938  rout->dwCurrentState = cur->dwCurrentState;
939  rout->dwEventState = cur->dwEventState;
940  rout->cbAtr = cur->cbAtr;
941  CopyMemory(&(rout->rgbAtr), cur->rgbAtr, sizeof(rout->rgbAtr));
942  }
943 
944  status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
945 fail:
946  free(ret.rgReaderStates);
947  free(rgReaderStates);
948  if (status != SCARD_S_SUCCESS)
949  return status;
950  return ret.ReturnCode;
951 }
952 
953 static LONG smartcard_GetStatusChangeW_Call(scard_call_context* smartcard, wStream* out,
954  SMARTCARD_OPERATION* operation)
955 {
956  LONG status = STATUS_NO_MEMORY;
957  DWORD dwTimeOut = 0;
958  const DWORD dwTimeStep = 100;
959  GetStatusChange_Return ret = { 0 };
960  GetStatusChangeW_Call* call = NULL;
961  LPSCARD_READERSTATEW rgReaderStates = NULL;
962 
963  WINPR_ASSERT(smartcard);
964  WINPR_ASSERT(out);
965  WINPR_ASSERT(operation);
966 
967  call = &operation->call.getStatusChangeW;
968  dwTimeOut = call->dwTimeOut;
969 
970  if (call->cReaders > 0)
971  {
972  ret.cReaders = call->cReaders;
973  rgReaderStates = calloc(ret.cReaders, sizeof(SCARD_READERSTATEW));
974  ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return));
975  if (!rgReaderStates || !ret.rgReaderStates)
976  goto fail;
977  }
978 
979  for (UINT32 x = 0; x < MAX(1, dwTimeOut);)
980  {
981  if (call->cReaders > 0)
982  memcpy(rgReaderStates, call->rgReaderStates,
983  call->cReaders * sizeof(SCARD_READERSTATEW));
984  {
985  ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeW, operation->hContext,
986  MIN(dwTimeOut, dwTimeStep), rgReaderStates, call->cReaders);
987  }
988  if (ret.ReturnCode != SCARD_E_TIMEOUT)
989  break;
990  if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
991  break;
992  if (dwTimeOut != INFINITE)
993  x += dwTimeStep;
994  }
995  scard_log_status_error(TAG, "SCardGetStatusChangeW", ret.ReturnCode);
996 
997  for (UINT32 index = 0; index < ret.cReaders; index++)
998  {
999  const SCARD_READERSTATEW* cur = &rgReaderStates[index];
1000  ReaderState_Return* rout = &ret.rgReaderStates[index];
1001 
1002  rout->dwCurrentState = cur->dwCurrentState;
1003  rout->dwEventState = cur->dwEventState;
1004  rout->cbAtr = cur->cbAtr;
1005  CopyMemory(&(rout->rgbAtr), cur->rgbAtr, sizeof(rout->rgbAtr));
1006  }
1007 
1008  status = smartcard_pack_get_status_change_return(out, &ret, TRUE);
1009 fail:
1010  free(ret.rgReaderStates);
1011  free(rgReaderStates);
1012  if (status != SCARD_S_SUCCESS)
1013  return status;
1014  return ret.ReturnCode;
1015 }
1016 
1017 static LONG smartcard_Cancel_Call(scard_call_context* smartcard, wStream* out,
1018  SMARTCARD_OPERATION* operation)
1019 {
1020  Long_Return ret = { 0 };
1021 
1022  WINPR_ASSERT(smartcard);
1023  WINPR_ASSERT(out);
1024  WINPR_ASSERT(operation);
1025 
1026  ret.ReturnCode = wrap(smartcard, SCardCancel, operation->hContext);
1027  scard_log_status_error(TAG, "SCardCancel", ret.ReturnCode);
1028  smartcard_trace_long_return(&ret, "Cancel");
1029  return ret.ReturnCode;
1030 }
1031 
1032 static LONG smartcard_ConnectA_Call(scard_call_context* smartcard, wStream* out,
1033  SMARTCARD_OPERATION* operation)
1034 {
1035  LONG status = 0;
1036  SCARDHANDLE hCard = 0;
1037  Connect_Return ret = { 0 };
1038  ConnectA_Call* call = NULL;
1039 
1040  WINPR_ASSERT(smartcard);
1041  WINPR_ASSERT(out);
1042  WINPR_ASSERT(operation);
1043 
1044  call = &operation->call.connectA;
1045 
1046  if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1047  (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1048  {
1049  call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1050  }
1051 
1052  ret.ReturnCode = wrap(smartcard, SCardConnectA, operation->hContext, (char*)call->szReader,
1053  call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1054  &ret.dwActiveProtocol);
1055  smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1056  smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1057 
1058  status = smartcard_pack_connect_return(out, &ret);
1059  if (status != SCARD_S_SUCCESS)
1060  goto out_fail;
1061 
1062  status = ret.ReturnCode;
1063 out_fail:
1064 
1065  return status;
1066 }
1067 
1068 static LONG smartcard_ConnectW_Call(scard_call_context* smartcard, wStream* out,
1069  SMARTCARD_OPERATION* operation)
1070 {
1071  LONG status = 0;
1072  SCARDHANDLE hCard = 0;
1073  Connect_Return ret = { 0 };
1074  ConnectW_Call* call = NULL;
1075 
1076  WINPR_ASSERT(smartcard);
1077  WINPR_ASSERT(out);
1078  WINPR_ASSERT(operation);
1079 
1080  call = &operation->call.connectW;
1081 
1082  if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
1083  (call->Common.dwShareMode != SCARD_SHARE_DIRECT))
1084  {
1085  call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx;
1086  }
1087 
1088  ret.ReturnCode = wrap(smartcard, SCardConnectW, operation->hContext, (WCHAR*)call->szReader,
1089  call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard,
1090  &ret.dwActiveProtocol);
1091  smartcard_scard_context_native_to_redir(&(ret.hContext), operation->hContext);
1092  smartcard_scard_handle_native_to_redir(&(ret.hCard), hCard);
1093 
1094  status = smartcard_pack_connect_return(out, &ret);
1095  if (status != SCARD_S_SUCCESS)
1096  goto out_fail;
1097 
1098  status = ret.ReturnCode;
1099 out_fail:
1100 
1101  return status;
1102 }
1103 
1104 static LONG smartcard_Reconnect_Call(scard_call_context* smartcard, wStream* out,
1105  SMARTCARD_OPERATION* operation)
1106 {
1107  LONG status = 0;
1108  Reconnect_Return ret = { 0 };
1109  Reconnect_Call* call = NULL;
1110 
1111  WINPR_ASSERT(smartcard);
1112  WINPR_ASSERT(out);
1113  WINPR_ASSERT(operation);
1114 
1115  call = &operation->call.reconnect;
1116  ret.ReturnCode =
1117  wrap(smartcard, SCardReconnect, operation->hCard, call->dwShareMode,
1118  call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
1119  scard_log_status_error(TAG, "SCardReconnect", ret.ReturnCode);
1120  status = smartcard_pack_reconnect_return(out, &ret);
1121  if (status != SCARD_S_SUCCESS)
1122  return status;
1123 
1124  return ret.ReturnCode;
1125 }
1126 
1127 static LONG smartcard_Disconnect_Call(scard_call_context* smartcard, wStream* out,
1128  SMARTCARD_OPERATION* operation)
1129 {
1130  Long_Return ret = { 0 };
1131  HCardAndDisposition_Call* call = NULL;
1132 
1133  WINPR_ASSERT(smartcard);
1134  WINPR_ASSERT(out);
1135  WINPR_ASSERT(operation);
1136 
1137  call = &operation->call.hCardAndDisposition;
1138 
1139  ret.ReturnCode = wrap(smartcard, SCardDisconnect, operation->hCard, call->dwDisposition);
1140  scard_log_status_error(TAG, "SCardDisconnect", ret.ReturnCode);
1141  smartcard_trace_long_return(&ret, "Disconnect");
1142 
1143  return ret.ReturnCode;
1144 }
1145 
1146 static LONG smartcard_BeginTransaction_Call(scard_call_context* smartcard, wStream* out,
1147  SMARTCARD_OPERATION* operation)
1148 {
1149  Long_Return ret = { 0 };
1150 
1151  WINPR_ASSERT(smartcard);
1152  WINPR_ASSERT(out);
1153  WINPR_ASSERT(operation);
1154 
1155  ret.ReturnCode = wrap(smartcard, SCardBeginTransaction, operation->hCard);
1156  scard_log_status_error(TAG, "SCardBeginTransaction", ret.ReturnCode);
1157  smartcard_trace_long_return(&ret, "BeginTransaction");
1158  return ret.ReturnCode;
1159 }
1160 
1161 static LONG smartcard_EndTransaction_Call(scard_call_context* smartcard, wStream* out,
1162  SMARTCARD_OPERATION* operation)
1163 {
1164  Long_Return ret = { 0 };
1165  HCardAndDisposition_Call* call = NULL;
1166 
1167  WINPR_ASSERT(smartcard);
1168  WINPR_ASSERT(out);
1169  WINPR_ASSERT(operation);
1170 
1171  call = &operation->call.hCardAndDisposition;
1172 
1173  ret.ReturnCode = wrap(smartcard, SCardEndTransaction, operation->hCard, call->dwDisposition);
1174  scard_log_status_error(TAG, "SCardEndTransaction", ret.ReturnCode);
1175  smartcard_trace_long_return(&ret, "EndTransaction");
1176  return ret.ReturnCode;
1177 }
1178 
1179 static LONG smartcard_State_Call(scard_call_context* smartcard, wStream* out,
1180  SMARTCARD_OPERATION* operation)
1181 {
1182  LONG status = 0;
1183  State_Return ret = { 0 };
1184 
1185  WINPR_ASSERT(smartcard);
1186  WINPR_ASSERT(out);
1187  WINPR_ASSERT(operation);
1188 
1189  ret.cbAtrLen = SCARD_ATR_LENGTH;
1190  ret.ReturnCode = wrap(smartcard, SCardState, operation->hCard, &ret.dwState, &ret.dwProtocol,
1191  (BYTE*)&ret.rgAtr, &ret.cbAtrLen);
1192 
1193  scard_log_status_error(TAG, "SCardState", ret.ReturnCode);
1194  status = smartcard_pack_state_return(out, &ret);
1195  if (status != SCARD_S_SUCCESS)
1196  return status;
1197 
1198  return ret.ReturnCode;
1199 }
1200 
1201 static LONG smartcard_StatusA_Call(scard_call_context* smartcard, wStream* out,
1202  SMARTCARD_OPERATION* operation)
1203 {
1204  LONG status = 0;
1205  Status_Return ret = { 0 };
1206  DWORD cchReaderLen = 0;
1207  DWORD cbAtrLen = 0;
1208  LPSTR mszReaderNames = NULL;
1209  Status_Call* call = NULL;
1210 
1211  WINPR_ASSERT(smartcard);
1212  WINPR_ASSERT(out);
1213  WINPR_ASSERT(operation);
1214 
1215  call = &operation->call.status;
1216 
1217  call->cbAtrLen = 32;
1218  cbAtrLen = call->cbAtrLen;
1219 
1220  if (call->fmszReaderNamesIsNULL)
1221  cchReaderLen = 0;
1222  else
1223  cchReaderLen = SCARD_AUTOALLOCATE;
1224 
1225  status = ret.ReturnCode =
1226  wrap(smartcard, SCardStatusA, operation->hCard,
1227  call->fmszReaderNamesIsNULL ? NULL : (LPSTR)&mszReaderNames, &cchReaderLen,
1228  &ret.dwState, &ret.dwProtocol, cbAtrLen ? (BYTE*)&ret.pbAtr : NULL, &cbAtrLen);
1229 
1230  scard_log_status_error(TAG, "SCardStatusA", status);
1231  if (cchReaderLen == SCARD_AUTOALLOCATE)
1232  return SCARD_F_UNKNOWN_ERROR;
1233 
1234  if (status == SCARD_S_SUCCESS)
1235  {
1236  if (!call->fmszReaderNamesIsNULL)
1237  ret.mszReaderNames = (BYTE*)mszReaderNames;
1238 
1239  ret.cBytes = cchReaderLen;
1240 
1241  if (call->cbAtrLen)
1242  ret.cbAtrLen = cbAtrLen;
1243  }
1244 
1245  status = smartcard_pack_status_return(out, &ret, FALSE);
1246 
1247  if (mszReaderNames)
1248  wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1249 
1250  if (status != SCARD_S_SUCCESS)
1251  return status;
1252  return ret.ReturnCode;
1253 }
1254 
1255 static LONG smartcard_StatusW_Call(scard_call_context* smartcard, wStream* out,
1256  SMARTCARD_OPERATION* operation)
1257 {
1258  LONG status = 0;
1259  Status_Return ret = { 0 };
1260  LPWSTR mszReaderNames = NULL;
1261  Status_Call* call = NULL;
1262  DWORD cbAtrLen = 0;
1263 
1264  WINPR_ASSERT(smartcard);
1265  WINPR_ASSERT(out);
1266  WINPR_ASSERT(operation);
1267 
1268  call = &operation->call.status;
1269 
1274  cbAtrLen = call->cbAtrLen = 32;
1275 
1276  if (call->fmszReaderNamesIsNULL)
1277  ret.cBytes = 0;
1278  else
1279  ret.cBytes = SCARD_AUTOALLOCATE;
1280 
1281  status = ret.ReturnCode =
1282  wrap(smartcard, SCardStatusW, operation->hCard,
1283  call->fmszReaderNamesIsNULL ? NULL : (LPWSTR)&mszReaderNames, &ret.cBytes,
1284  &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.pbAtr, &cbAtrLen);
1285  scard_log_status_error(TAG, "SCardStatusW", status);
1286  if (ret.cBytes == SCARD_AUTOALLOCATE)
1287  return SCARD_F_UNKNOWN_ERROR;
1288 
1289  if (status == SCARD_S_SUCCESS)
1290  {
1291  if (!call->fmszReaderNamesIsNULL)
1292  ret.mszReaderNames = (BYTE*)mszReaderNames;
1293 
1294  ret.cbAtrLen = cbAtrLen;
1295  }
1296 
1297  /* SCardStatusW returns number of characters, we need number of bytes */
1298  WINPR_ASSERT(ret.cBytes < SCARD_AUTOALLOCATE / sizeof(WCHAR));
1299  const size_t blen = sizeof(WCHAR) * ret.cBytes;
1300  WINPR_ASSERT(blen <= UINT32_MAX);
1301  ret.cBytes = (UINT32)blen;
1302 
1303  status = smartcard_pack_status_return(out, &ret, TRUE);
1304  if (status != SCARD_S_SUCCESS)
1305  return status;
1306 
1307  if (mszReaderNames)
1308  wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1309 
1310  return ret.ReturnCode;
1311 }
1312 
1313 static LONG smartcard_Transmit_Call(scard_call_context* smartcard, wStream* out,
1314  SMARTCARD_OPERATION* operation)
1315 {
1316  LONG status = 0;
1317  Transmit_Return ret = { 0 };
1318  Transmit_Call* call = NULL;
1319 
1320  WINPR_ASSERT(smartcard);
1321  WINPR_ASSERT(out);
1322  WINPR_ASSERT(operation);
1323 
1324  call = &operation->call.transmit;
1325  ret.cbRecvLength = 0;
1326  ret.pbRecvBuffer = NULL;
1327 
1328  if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
1329  {
1330  if (call->cbRecvLength >= 66560)
1331  call->cbRecvLength = 66560;
1332 
1333  ret.cbRecvLength = call->cbRecvLength;
1334  ret.pbRecvBuffer = (BYTE*)malloc(ret.cbRecvLength);
1335 
1336  if (!ret.pbRecvBuffer)
1337  return STATUS_NO_MEMORY;
1338  }
1339 
1340  ret.pioRecvPci = call->pioRecvPci;
1341  ret.ReturnCode =
1342  wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
1343  call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
1344 
1345  scard_log_status_error(TAG, "SCardTransmit", ret.ReturnCode);
1346 
1347  status = smartcard_pack_transmit_return(out, &ret);
1348  free(ret.pbRecvBuffer);
1349 
1350  if (status != SCARD_S_SUCCESS)
1351  return status;
1352  return ret.ReturnCode;
1353 }
1354 
1355 static LONG smartcard_Control_Call(scard_call_context* smartcard, wStream* out,
1356  SMARTCARD_OPERATION* operation)
1357 {
1358  LONG status = 0;
1359  Control_Return ret = { 0 };
1360  Control_Call* call = NULL;
1361 
1362  WINPR_ASSERT(smartcard);
1363  WINPR_ASSERT(out);
1364  WINPR_ASSERT(operation);
1365 
1366  call = &operation->call.control;
1367  ret.cbOutBufferSize = call->cbOutBufferSize;
1368  ret.pvOutBuffer = (BYTE*)malloc(call->cbOutBufferSize);
1369 
1370  if (!ret.pvOutBuffer)
1371  return SCARD_E_NO_MEMORY;
1372 
1373  ret.ReturnCode =
1374  wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
1375  call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
1376  scard_log_status_error(TAG, "SCardControl", ret.ReturnCode);
1377  status = smartcard_pack_control_return(out, &ret);
1378 
1379  free(ret.pvOutBuffer);
1380  if (status != SCARD_S_SUCCESS)
1381  return status;
1382  return ret.ReturnCode;
1383 }
1384 
1385 static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard, wStream* out,
1386  SMARTCARD_OPERATION* operation)
1387 {
1388  BOOL autoAllocate = FALSE;
1389  LONG status = 0;
1390  DWORD cbAttrLen = 0;
1391  LPBYTE pbAttr = NULL;
1392  GetAttrib_Return ret = { 0 };
1393  const GetAttrib_Call* call = NULL;
1394 
1395  WINPR_ASSERT(smartcard);
1396  WINPR_ASSERT(operation);
1397 
1398  call = &operation->call.getAttrib;
1399 
1400  if (!call->fpbAttrIsNULL)
1401  {
1402  autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE) ? TRUE : FALSE;
1403  cbAttrLen = call->cbAttrLen;
1404  if (cbAttrLen && !autoAllocate)
1405  {
1406  ret.pbAttr = (BYTE*)malloc(cbAttrLen);
1407 
1408  if (!ret.pbAttr)
1409  return SCARD_E_NO_MEMORY;
1410  }
1411 
1412  pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
1413  }
1414 
1415  ret.ReturnCode =
1416  wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
1417  scard_log_status_error(TAG, "SCardGetAttrib", ret.ReturnCode);
1418  if (cbAttrLen == SCARD_AUTOALLOCATE)
1419  return SCARD_F_UNKNOWN_ERROR;
1420 
1421  ret.cbAttrLen = cbAttrLen;
1422 
1423  status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
1424 
1425  if (autoAllocate)
1426  wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
1427  else
1428  free(ret.pbAttr);
1429  return status;
1430 }
1431 
1432 static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard, wStream* out,
1433  SMARTCARD_OPERATION* operation)
1434 {
1435  Long_Return ret = { 0 };
1436  SetAttrib_Call* call = NULL;
1437 
1438  WINPR_ASSERT(smartcard);
1439  WINPR_ASSERT(out);
1440  WINPR_ASSERT(operation);
1441 
1442  call = &operation->call.setAttrib;
1443 
1444  ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
1445  call->cbAttrLen);
1446  scard_log_status_error(TAG, "SCardSetAttrib", ret.ReturnCode);
1447  smartcard_trace_long_return(&ret, "SetAttrib");
1448 
1449  return ret.ReturnCode;
1450 }
1451 
1452 static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard, wStream* out,
1453  SMARTCARD_OPERATION* operation)
1454 {
1455  LONG status = SCARD_S_SUCCESS;
1456 
1457  WINPR_ASSERT(smartcard);
1458  WINPR_ASSERT(out);
1459  WINPR_UNUSED(operation);
1460 
1461  if (!smartcard->StartedEvent)
1462  smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
1463 
1464  if (!smartcard->StartedEvent)
1465  status = SCARD_E_NO_SERVICE;
1466 
1467  return status;
1468 }
1469 
1470 static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard, wStream* out,
1471  SMARTCARD_OPERATION* operation)
1472 {
1473  LONG status = 0;
1474  GetStatusChange_Return ret = { 0 };
1475  LPSCARD_READERSTATEA state = NULL;
1476  LPSCARD_READERSTATEA states = NULL;
1477  LocateCardsByATRA_Call* call = NULL;
1478 
1479  WINPR_ASSERT(smartcard);
1480  WINPR_ASSERT(operation);
1481 
1482  call = &operation->call.locateCardsByATRA;
1483  states = (LPSCARD_READERSTATEA)calloc(call->cReaders, sizeof(SCARD_READERSTATEA));
1484 
1485  if (!states)
1486  return STATUS_NO_MEMORY;
1487 
1488  for (UINT32 i = 0; i < call->cReaders; i++)
1489  {
1490  states[i].szReader = call->rgReaderStates[i].szReader;
1491  states[i].dwCurrentState = call->rgReaderStates[i].dwCurrentState;
1492  states[i].dwEventState = call->rgReaderStates[i].dwEventState;
1493  states[i].cbAtr = call->rgReaderStates[i].cbAtr;
1494  CopyMemory(&(states[i].rgbAtr), &(call->rgReaderStates[i].rgbAtr), 36);
1495  }
1496 
1497  status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1498  0x000001F4, states, call->cReaders);
1499 
1500  scard_log_status_error(TAG, "SCardGetStatusChangeA", status);
1501  for (UINT32 i = 0; i < call->cAtrs; i++)
1502  {
1503  for (UINT32 j = 0; j < call->cReaders; j++)
1504  {
1505  for (UINT32 k = 0; k < call->rgAtrMasks[i].cbAtr; k++)
1506  {
1507  if ((call->rgAtrMasks[i].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]) !=
1508  (states[j].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]))
1509  {
1510  break;
1511  }
1512 
1513  states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1514  }
1515  }
1516  }
1517 
1518  ret.cReaders = call->cReaders;
1519  ret.rgReaderStates = NULL;
1520 
1521  if (ret.cReaders > 0)
1522  ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return));
1523 
1524  if (!ret.rgReaderStates)
1525  {
1526  free(states);
1527  return STATUS_NO_MEMORY;
1528  }
1529 
1530  for (UINT32 i = 0; i < ret.cReaders; i++)
1531  {
1532  state = &states[i];
1533  ret.rgReaderStates[i].dwCurrentState = state->dwCurrentState;
1534  ret.rgReaderStates[i].dwEventState = state->dwEventState;
1535  ret.rgReaderStates[i].cbAtr = state->cbAtr;
1536  CopyMemory(&(ret.rgReaderStates[i].rgbAtr), &(state->rgbAtr),
1537  sizeof(ret.rgReaderStates[i].rgbAtr));
1538  }
1539 
1540  free(states);
1541 
1542  status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1543 
1544  free(ret.rgReaderStates);
1545  if (status != SCARD_S_SUCCESS)
1546  return status;
1547  return ret.ReturnCode;
1548 }
1549 
1550 LONG smartcard_irp_device_control_call(scard_call_context* smartcard, wStream* out,
1551  UINT32* pIoStatus, SMARTCARD_OPERATION* operation)
1552 {
1553  LONG result = 0;
1554  UINT32 offset = 0;
1555  UINT32 ioControlCode = 0;
1556  size_t outputBufferLength = 0;
1557  size_t objectBufferLength = 0;
1558 
1559  WINPR_ASSERT(smartcard);
1560  WINPR_ASSERT(out);
1561  WINPR_ASSERT(pIoStatus);
1562  WINPR_ASSERT(operation);
1563 
1564  ioControlCode = operation->ioControlCode;
1572  if (!Stream_EnsureRemainingCapacity(out, 2048))
1573  return SCARD_E_NO_MEMORY;
1574 
1575  /* Device Control Response */
1576  Stream_Write_UINT32(out, 0); /* OutputBufferLength (4 bytes) */
1577  Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH); /* CommonTypeHeader (8 bytes) */
1578  Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH); /* PrivateTypeHeader (8 bytes) */
1579  Stream_Write_UINT32(out, 0); /* Result (4 bytes) */
1580 
1581  /* Call */
1582  switch (ioControlCode)
1583  {
1584  case SCARD_IOCTL_ESTABLISHCONTEXT:
1585  result = smartcard_EstablishContext_Call(smartcard, out, operation);
1586  break;
1587 
1588  case SCARD_IOCTL_RELEASECONTEXT:
1589  result = smartcard_ReleaseContext_Call(smartcard, out, operation);
1590  break;
1591 
1592  case SCARD_IOCTL_ISVALIDCONTEXT:
1593  result = smartcard_IsValidContext_Call(smartcard, out, operation);
1594  break;
1595 
1596  case SCARD_IOCTL_LISTREADERGROUPSA:
1597  result = smartcard_ListReaderGroupsA_Call(smartcard, out, operation);
1598  break;
1599 
1600  case SCARD_IOCTL_LISTREADERGROUPSW:
1601  result = smartcard_ListReaderGroupsW_Call(smartcard, out, operation);
1602  break;
1603 
1604  case SCARD_IOCTL_LISTREADERSA:
1605  result = smartcard_ListReadersA_Call(smartcard, out, operation);
1606  break;
1607 
1608  case SCARD_IOCTL_LISTREADERSW:
1609  result = smartcard_ListReadersW_Call(smartcard, out, operation);
1610  break;
1611 
1612  case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1613  result = smartcard_IntroduceReaderGroupA_Call(smartcard, out, operation);
1614  break;
1615 
1616  case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1617  result = smartcard_IntroduceReaderGroupW_Call(smartcard, out, operation);
1618  break;
1619 
1620  case SCARD_IOCTL_FORGETREADERGROUPA:
1621  result = smartcard_ForgetReaderA_Call(smartcard, out, operation);
1622  break;
1623 
1624  case SCARD_IOCTL_FORGETREADERGROUPW:
1625  result = smartcard_ForgetReaderW_Call(smartcard, out, operation);
1626  break;
1627 
1628  case SCARD_IOCTL_INTRODUCEREADERA:
1629  result = smartcard_IntroduceReaderA_Call(smartcard, out, operation);
1630  break;
1631 
1632  case SCARD_IOCTL_INTRODUCEREADERW:
1633  result = smartcard_IntroduceReaderW_Call(smartcard, out, operation);
1634  break;
1635 
1636  case SCARD_IOCTL_FORGETREADERA:
1637  result = smartcard_ForgetReaderA_Call(smartcard, out, operation);
1638  break;
1639 
1640  case SCARD_IOCTL_FORGETREADERW:
1641  result = smartcard_ForgetReaderW_Call(smartcard, out, operation);
1642  break;
1643 
1644  case SCARD_IOCTL_ADDREADERTOGROUPA:
1645  result = smartcard_AddReaderToGroupA_Call(smartcard, out, operation);
1646  break;
1647 
1648  case SCARD_IOCTL_ADDREADERTOGROUPW:
1649  result = smartcard_AddReaderToGroupW_Call(smartcard, out, operation);
1650  break;
1651 
1652  case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1653  result = smartcard_RemoveReaderFromGroupA_Call(smartcard, out, operation);
1654  break;
1655 
1656  case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1657  result = smartcard_RemoveReaderFromGroupW_Call(smartcard, out, operation);
1658  break;
1659 
1660  case SCARD_IOCTL_LOCATECARDSA:
1661  result = smartcard_LocateCardsA_Call(smartcard, out, operation);
1662  break;
1663 
1664  case SCARD_IOCTL_LOCATECARDSW:
1665  result = smartcard_LocateCardsW_Call(smartcard, out, operation);
1666  break;
1667 
1668  case SCARD_IOCTL_GETSTATUSCHANGEA:
1669  result = smartcard_GetStatusChangeA_Call(smartcard, out, operation);
1670  break;
1671 
1672  case SCARD_IOCTL_GETSTATUSCHANGEW:
1673  result = smartcard_GetStatusChangeW_Call(smartcard, out, operation);
1674  break;
1675 
1676  case SCARD_IOCTL_CANCEL:
1677  result = smartcard_Cancel_Call(smartcard, out, operation);
1678  break;
1679 
1680  case SCARD_IOCTL_CONNECTA:
1681  result = smartcard_ConnectA_Call(smartcard, out, operation);
1682  break;
1683 
1684  case SCARD_IOCTL_CONNECTW:
1685  result = smartcard_ConnectW_Call(smartcard, out, operation);
1686  break;
1687 
1688  case SCARD_IOCTL_RECONNECT:
1689  result = smartcard_Reconnect_Call(smartcard, out, operation);
1690  break;
1691 
1692  case SCARD_IOCTL_DISCONNECT:
1693  result = smartcard_Disconnect_Call(smartcard, out, operation);
1694  break;
1695 
1696  case SCARD_IOCTL_BEGINTRANSACTION:
1697  result = smartcard_BeginTransaction_Call(smartcard, out, operation);
1698  break;
1699 
1700  case SCARD_IOCTL_ENDTRANSACTION:
1701  result = smartcard_EndTransaction_Call(smartcard, out, operation);
1702  break;
1703 
1704  case SCARD_IOCTL_STATE:
1705  result = smartcard_State_Call(smartcard, out, operation);
1706  break;
1707 
1708  case SCARD_IOCTL_STATUSA:
1709  result = smartcard_StatusA_Call(smartcard, out, operation);
1710  break;
1711 
1712  case SCARD_IOCTL_STATUSW:
1713  result = smartcard_StatusW_Call(smartcard, out, operation);
1714  break;
1715 
1716  case SCARD_IOCTL_TRANSMIT:
1717  result = smartcard_Transmit_Call(smartcard, out, operation);
1718  break;
1719 
1720  case SCARD_IOCTL_CONTROL:
1721  result = smartcard_Control_Call(smartcard, out, operation);
1722  break;
1723 
1724  case SCARD_IOCTL_GETATTRIB:
1725  result = smartcard_GetAttrib_Call(smartcard, out, operation);
1726  break;
1727 
1728  case SCARD_IOCTL_SETATTRIB:
1729  result = smartcard_SetAttrib_Call(smartcard, out, operation);
1730  break;
1731 
1732  case SCARD_IOCTL_ACCESSSTARTEDEVENT:
1733  result = smartcard_AccessStartedEvent_Call(smartcard, out, operation);
1734  break;
1735 
1736  case SCARD_IOCTL_LOCATECARDSBYATRA:
1737  result = smartcard_LocateCardsByATRA_Call(smartcard, out, operation);
1738  break;
1739 
1740  case SCARD_IOCTL_LOCATECARDSBYATRW:
1741  result = smartcard_LocateCardsW_Call(smartcard, out, operation);
1742  break;
1743 
1744  case SCARD_IOCTL_READCACHEA:
1745  result = smartcard_ReadCacheA_Call(smartcard, out, operation);
1746  break;
1747 
1748  case SCARD_IOCTL_READCACHEW:
1749  result = smartcard_ReadCacheW_Call(smartcard, out, operation);
1750  break;
1751 
1752  case SCARD_IOCTL_WRITECACHEA:
1753  result = smartcard_WriteCacheA_Call(smartcard, out, operation);
1754  break;
1755 
1756  case SCARD_IOCTL_WRITECACHEW:
1757  result = smartcard_WriteCacheW_Call(smartcard, out, operation);
1758  break;
1759 
1760  case SCARD_IOCTL_GETTRANSMITCOUNT:
1761  result = smartcard_GetTransmitCount_Call(smartcard, out, operation);
1762  break;
1763 
1764  case SCARD_IOCTL_RELEASETARTEDEVENT:
1765  result = smartcard_ReleaseStartedEvent_Call(smartcard, out, operation);
1766  break;
1767 
1768  case SCARD_IOCTL_GETREADERICON:
1769  result = smartcard_GetReaderIcon_Call(smartcard, out, operation);
1770  break;
1771 
1772  case SCARD_IOCTL_GETDEVICETYPEID:
1773  result = smartcard_GetDeviceTypeId_Call(smartcard, out, operation);
1774  break;
1775 
1776  default:
1777  result = STATUS_UNSUCCESSFUL;
1778  break;
1779  }
1780 
1787  if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
1788  (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
1789  {
1790  offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
1791  smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
1792  }
1793 
1794  if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
1795  (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
1796  (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
1797  {
1798  WLog_WARN(TAG, "IRP failure: %s (0x%08" PRIX32 "), status: %s (0x%08" PRIX32 ")",
1799  scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
1800  SCardGetErrorString(result), result);
1801  }
1802 
1803  *pIoStatus = STATUS_SUCCESS;
1804 
1805  if ((result & 0xC0000000L) == 0xC0000000L)
1806  {
1807  /* NTSTATUS error */
1808  *pIoStatus = (UINT32)result;
1809  WLog_WARN(TAG, "IRP failure: %s (0x%08" PRIX32 "), ntstatus: 0x%08" PRIX32 "",
1810  scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, result);
1811  }
1812 
1813  Stream_SealLength(out);
1814  outputBufferLength = Stream_Length(out);
1815  WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH - 4U);
1816  outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1817  WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1818  objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
1819  WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
1820  WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
1821  Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1822  /* Device Control Response */
1823  Stream_Write_UINT32(out, (UINT32)outputBufferLength); /* OutputBufferLength (4 bytes) */
1824  smartcard_pack_common_type_header(out); /* CommonTypeHeader (8 bytes) */
1825  smartcard_pack_private_type_header(
1826  out, (UINT32)objectBufferLength); /* PrivateTypeHeader (8 bytes) */
1827  Stream_Write_INT32(out, result); /* Result (4 bytes) */
1828  Stream_SetPosition(out, Stream_Length(out));
1829  return SCARD_S_SUCCESS;
1830 }
1831 
1832 void context_free(void* arg)
1833 {
1834  struct s_scard_context_element* element = arg;
1835  if (!arg)
1836  return;
1837 
1838  if (element->fn_free)
1839  element->fn_free(element->context);
1840  free(element);
1841 }
1842 
1843 scard_call_context* smartcard_call_context_new(const rdpSettings* settings)
1844 {
1845  wObject* obj = NULL;
1846  scard_call_context* ctx = NULL;
1847 
1848  WINPR_ASSERT(settings);
1849  ctx = calloc(1, sizeof(scard_call_context));
1850  if (!ctx)
1851  goto fail;
1852 
1853  ctx->stopEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
1854  if (!ctx->stopEvent)
1855  goto fail;
1856 
1857  ctx->names = LinkedList_New();
1858  if (!ctx->names)
1859  goto fail;
1860 
1861 #if defined(WITH_SMARTCARD_EMULATE)
1862  ctx->useEmulatedCard = freerdp_settings_get_bool(settings, FreeRDP_SmartcardEmulation);
1863 #endif
1864 
1865  if (ctx->useEmulatedCard)
1866  {
1867 #if defined(WITH_SMARTCARD_EMULATE)
1868  ctx->emulation = Emulate_New(settings);
1869  if (!ctx->emulation)
1870  goto fail;
1871 #else
1872  WLog_ERR(TAG, "Smartcard emulation requested, but not supported!");
1873  goto fail;
1874 #endif
1875  }
1876  else
1877  {
1878  const char* WinSCardModule = freerdp_settings_get_string(settings, FreeRDP_WinSCardModule);
1879  if (WinSCardModule)
1880  {
1881  ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
1882 
1883  if (!ctx->hWinSCardLibrary)
1884  {
1885  WLog_ERR(TAG, "Failed to load WinSCard library: '%s'", WinSCardModule);
1886  goto fail;
1887  }
1888 
1889  if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
1890  goto fail;
1891  ctx->pWinSCardApi = &ctx->WinSCardApi;
1892  }
1893  else
1894  {
1895  ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
1896  }
1897 
1898  if (!ctx->pWinSCardApi)
1899  {
1900  WLog_ERR(TAG, "Failed to load WinSCard API!");
1901  goto fail;
1902  }
1903  }
1904 
1905  ctx->rgSCardContextList = HashTable_New(FALSE);
1906  if (!ctx->rgSCardContextList)
1907  goto fail;
1908 
1909  obj = HashTable_ValueObject(ctx->rgSCardContextList);
1910  WINPR_ASSERT(obj);
1911  obj->fnObjectFree = context_free;
1912 
1913  return ctx;
1914 fail:
1915  WINPR_PRAGMA_DIAG_PUSH
1916  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1917  smartcard_call_context_free(ctx);
1918  WINPR_PRAGMA_DIAG_POP
1919  return NULL;
1920 }
1921 
1922 void smartcard_call_context_free(scard_call_context* ctx)
1923 {
1924  if (!ctx)
1925  return;
1926 
1927  smartcard_call_context_signal_stop(ctx, FALSE);
1928 
1929  LinkedList_Free(ctx->names);
1930  if (ctx->StartedEvent)
1931  {
1932  WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
1933  wrap(ctx, SCardReleaseStartedEvent);
1934  }
1935 
1936  if (ctx->useEmulatedCard)
1937  {
1938 #ifdef WITH_SMARTCARD_EMULATE
1939  if (ctx->emulation)
1940  {
1941  Emulate_Free(ctx->emulation);
1942  ctx->emulation = NULL;
1943  }
1944 #endif
1945  }
1946 
1947  if (ctx->hWinSCardLibrary)
1948  {
1949  ZeroMemory(&ctx->WinSCardApi, sizeof(SCardApiFunctionTable));
1950  FreeLibrary(ctx->hWinSCardLibrary);
1951  ctx->hWinSCardLibrary = NULL;
1952  }
1953 
1954  ctx->pWinSCardApi = NULL;
1955 
1956  HashTable_Free(ctx->rgSCardContextList);
1957  (void)CloseHandle(ctx->stopEvent);
1958  free(ctx);
1959 }
1960 
1961 BOOL smartcard_call_context_add(scard_call_context* ctx, const char* name)
1962 {
1963  WINPR_ASSERT(ctx);
1964  WINPR_ASSERT(name);
1965  return LinkedList_AddLast(ctx->names, name);
1966 }
1967 
1968 BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
1969 {
1970  WINPR_ASSERT(ctx);
1971  if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
1972  {
1973  wrap(ctx, SCardCancel, hContext);
1974  }
1975  return TRUE;
1976 }
1977 
1978 BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
1979 {
1980  WINPR_ASSERT(ctx);
1981  wrap(ctx, SCardReleaseContext, hContext);
1982  return TRUE;
1983 }
1984 
1985 BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
1986 {
1987  WINPR_ASSERT(ctx);
1988 
1989  HashTable_Clear(ctx->rgSCardContextList);
1990  return TRUE;
1991 }
1992 
1993 BOOL smarcard_call_set_callbacks(scard_call_context* ctx, void* userdata,
1994  void* (*fn_new)(void*, SCARDCONTEXT), void (*fn_free)(void*))
1995 {
1996  WINPR_ASSERT(ctx);
1997  ctx->userdata = userdata;
1998  ctx->fn_new = fn_new;
1999  ctx->fn_free = fn_free;
2000  return TRUE;
2001 }
2002 
2003 void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2004 {
2005  struct s_scard_context_element* element = NULL;
2006 
2007  WINPR_ASSERT(ctx);
2008  element = HashTable_GetItemValue(ctx->rgSCardContextList, (void*)hContext);
2009  if (!element)
2010  return NULL;
2011  return element->context;
2012 }
2013 
2014 BOOL smartcard_call_is_configured(scard_call_context* ctx)
2015 {
2016  WINPR_ASSERT(ctx);
2017 
2018 #if defined(WITH_SMARTCARD_EMULATE)
2019  if (ctx->useEmulatedCard)
2020  return Emulate_IsConfigured(ctx->emulation);
2021 #endif
2022 
2023  return FALSE;
2024 }
2025 
2026 BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
2027 {
2028  WINPR_ASSERT(ctx);
2029  if (!ctx->stopEvent)
2030  return TRUE;
2031 
2032  if (reset)
2033  return ResetEvent(ctx->stopEvent);
2034  else
2035  return SetEvent(ctx->stopEvent);
2036 }
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
This struct contains function pointer to initialize/free objects.
Definition: collections.h:57