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