FreeRDP
Loading...
Searching...
No Matches
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 size_t blen = 0;
1323 if (status == SCARD_S_SUCCESS)
1324 {
1325 if (!call->fmszReaderNamesIsNULL)
1326 ret.mszReaderNames = (BYTE*)mszReaderNames;
1327
1328 ret.cbAtrLen = cbAtrLen;
1329 }
1330
1331 if (ret.cBytes != SCARD_AUTOALLOCATE)
1332 {
1333 /* SCardStatusW returns number of characters, we need number of bytes */
1334 WINPR_ASSERT(ret.cBytes < SCARD_AUTOALLOCATE / sizeof(WCHAR));
1335 blen = sizeof(WCHAR) * ret.cBytes;
1336 WINPR_ASSERT(blen <= UINT32_MAX);
1337 ret.cBytes = (UINT32)blen;
1338 }
1339
1340 status = smartcard_pack_status_return(out, &ret, TRUE);
1341 if (status != SCARD_S_SUCCESS)
1342 return status;
1343
1344 if (mszReaderNames)
1345 wrap(smartcard, SCardFreeMemory, operation->hContext, mszReaderNames);
1346
1347 return ret.ReturnCode;
1348}
1349
1350static LONG smartcard_Transmit_Call(scard_call_context* smartcard, wStream* out,
1351 SMARTCARD_OPERATION* operation)
1352{
1353 LONG status = 0;
1354 Transmit_Return ret = { 0 };
1355 Transmit_Call* call = NULL;
1356
1357 WINPR_ASSERT(smartcard);
1358 WINPR_ASSERT(out);
1359 WINPR_ASSERT(operation);
1360
1361 call = &operation->call.transmit;
1362 ret.cbRecvLength = 0;
1363 ret.pbRecvBuffer = NULL;
1364
1365 if (call->cbRecvLength && !call->fpbRecvBufferIsNULL)
1366 {
1367 if (call->cbRecvLength >= 66560)
1368 call->cbRecvLength = 66560;
1369
1370 ret.cbRecvLength = call->cbRecvLength;
1371 ret.pbRecvBuffer = (BYTE*)malloc(ret.cbRecvLength);
1372
1373 if (!ret.pbRecvBuffer)
1374 return STATUS_NO_MEMORY;
1375 }
1376
1377 ret.pioRecvPci = call->pioRecvPci;
1378 ret.ReturnCode =
1379 wrap(smartcard, SCardTransmit, operation->hCard, call->pioSendPci, call->pbSendBuffer,
1380 call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
1381
1382 scard_log_status_error_wlog(smartcard->log, "SCardTransmit", ret.ReturnCode);
1383
1384 status = smartcard_pack_transmit_return(out, &ret);
1385 free(ret.pbRecvBuffer);
1386
1387 if (status != SCARD_S_SUCCESS)
1388 return status;
1389 return ret.ReturnCode;
1390}
1391
1392static LONG smartcard_Control_Call(scard_call_context* smartcard, wStream* out,
1393 SMARTCARD_OPERATION* operation)
1394{
1395 LONG status = 0;
1396 Control_Return ret = { 0 };
1397 Control_Call* call = NULL;
1398
1399 WINPR_ASSERT(smartcard);
1400 WINPR_ASSERT(out);
1401 WINPR_ASSERT(operation);
1402
1403 call = &operation->call.control;
1404 ret.cbOutBufferSize = call->cbOutBufferSize;
1405 ret.pvOutBuffer = (BYTE*)malloc(call->cbOutBufferSize);
1406
1407 if (!ret.pvOutBuffer)
1408 return SCARD_E_NO_MEMORY;
1409
1410 ret.ReturnCode =
1411 wrap(smartcard, SCardControl, operation->hCard, call->dwControlCode, call->pvInBuffer,
1412 call->cbInBufferSize, ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
1413 scard_log_status_error_wlog(smartcard->log, "SCardControl", ret.ReturnCode);
1414 status = smartcard_pack_control_return(out, &ret);
1415
1416 free(ret.pvOutBuffer);
1417 if (status != SCARD_S_SUCCESS)
1418 return status;
1419 return ret.ReturnCode;
1420}
1421
1422static LONG smartcard_GetAttrib_Call(scard_call_context* smartcard, wStream* out,
1423 SMARTCARD_OPERATION* operation)
1424{
1425 BOOL autoAllocate = FALSE;
1426 LONG status = 0;
1427 DWORD cbAttrLen = 0;
1428 LPBYTE pbAttr = NULL;
1429 GetAttrib_Return ret = { 0 };
1430 const GetAttrib_Call* call = NULL;
1431
1432 WINPR_ASSERT(smartcard);
1433 WINPR_ASSERT(operation);
1434
1435 call = &operation->call.getAttrib;
1436
1437 if (!call->fpbAttrIsNULL)
1438 {
1439 autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE) ? TRUE : FALSE;
1440 cbAttrLen = call->cbAttrLen;
1441 if (cbAttrLen && !autoAllocate)
1442 {
1443 ret.pbAttr = (BYTE*)malloc(cbAttrLen);
1444
1445 if (!ret.pbAttr)
1446 return SCARD_E_NO_MEMORY;
1447 }
1448
1449 pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr;
1450 }
1451
1452 ret.ReturnCode =
1453 wrap(smartcard, SCardGetAttrib, operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen);
1454 scard_log_status_error_wlog(smartcard->log, "SCardGetAttrib", ret.ReturnCode);
1455 if ((ret.ReturnCode == SCARD_S_SUCCESS) && (cbAttrLen == SCARD_AUTOALLOCATE))
1456 return SCARD_F_UNKNOWN_ERROR;
1457
1458 ret.cbAttrLen = cbAttrLen;
1459
1460 status = smartcard_pack_get_attrib_return(out, &ret, call->dwAttrId, call->cbAttrLen);
1461
1462 if (autoAllocate)
1463 wrap(smartcard, SCardFreeMemory, operation->hContext, ret.pbAttr);
1464 else
1465 free(ret.pbAttr);
1466 return status;
1467}
1468
1469static LONG smartcard_SetAttrib_Call(scard_call_context* smartcard, WINPR_ATTR_UNUSED wStream* out,
1470 SMARTCARD_OPERATION* operation)
1471{
1472 Long_Return ret = { 0 };
1473 SetAttrib_Call* call = NULL;
1474
1475 WINPR_ASSERT(smartcard);
1476 WINPR_ASSERT(out);
1477 WINPR_ASSERT(operation);
1478
1479 call = &operation->call.setAttrib;
1480
1481 ret.ReturnCode = wrap(smartcard, SCardSetAttrib, operation->hCard, call->dwAttrId, call->pbAttr,
1482 call->cbAttrLen);
1483 scard_log_status_error_wlog(smartcard->log, "SCardSetAttrib", ret.ReturnCode);
1484 smartcard_trace_long_return_int(smartcard->log, &ret, "SetAttrib");
1485
1486 return ret.ReturnCode;
1487}
1488
1489static LONG smartcard_AccessStartedEvent_Call(scard_call_context* smartcard,
1490 WINPR_ATTR_UNUSED wStream* out,
1491 SMARTCARD_OPERATION* operation)
1492{
1493 LONG status = SCARD_S_SUCCESS;
1494
1495 WINPR_ASSERT(smartcard);
1496 WINPR_ASSERT(out);
1497 WINPR_UNUSED(operation);
1498
1499 if (!smartcard->StartedEvent)
1500 smartcard->StartedEvent = wrap_ptr(smartcard, SCardAccessStartedEvent);
1501
1502 if (!smartcard->StartedEvent)
1503 status = SCARD_E_NO_SERVICE;
1504
1505 return status;
1506}
1507
1508static LONG smartcard_LocateCardsByATRA_Call(scard_call_context* smartcard, wStream* out,
1509 SMARTCARD_OPERATION* operation)
1510{
1511 LONG status = 0;
1512 GetStatusChange_Return ret = { 0 };
1513 LPSCARD_READERSTATEA states = NULL;
1514 LocateCardsByATRA_Call* call = NULL;
1515
1516 WINPR_ASSERT(smartcard);
1517 WINPR_ASSERT(operation);
1518
1519 call = &operation->call.locateCardsByATRA;
1520 states = (LPSCARD_READERSTATEA)calloc(call->cReaders, sizeof(SCARD_READERSTATEA));
1521
1522 if (!states)
1523 return STATUS_NO_MEMORY;
1524
1525 for (UINT32 i = 0; i < call->cReaders; i++)
1526 {
1527 LPSCARD_READERSTATEA state = &states[i];
1528 state->szReader = call->rgReaderStates[i].szReader;
1529 state->dwCurrentState = call->rgReaderStates[i].dwCurrentState;
1530 state->dwEventState = call->rgReaderStates[i].dwEventState;
1531 state->cbAtr = call->rgReaderStates[i].cbAtr;
1532 CopyMemory(&(state->rgbAtr), &(call->rgReaderStates[i].rgbAtr), 36);
1533 }
1534
1535 status = ret.ReturnCode = wrap(smartcard, SCardGetStatusChangeA, operation->hContext,
1536 0x000001F4, states, call->cReaders);
1537
1538 scard_log_status_error_wlog(smartcard->log, "SCardGetStatusChangeA", status);
1539 for (UINT32 i = 0; i < call->cAtrs; i++)
1540 {
1541 for (UINT32 j = 0; j < call->cReaders; j++)
1542 {
1543 for (UINT32 k = 0; k < call->rgAtrMasks[i].cbAtr; k++)
1544 {
1545 if ((call->rgAtrMasks[i].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]) !=
1546 (states[j].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]))
1547 {
1548 break;
1549 }
1550
1551 states[j].dwEventState |= SCARD_STATE_ATRMATCH;
1552 }
1553 }
1554 }
1555
1556 ret.cReaders = call->cReaders;
1557 ret.rgReaderStates = NULL;
1558
1559 if (ret.cReaders > 0)
1560 ret.rgReaderStates = (ReaderState_Return*)calloc(ret.cReaders, sizeof(ReaderState_Return));
1561
1562 if (!ret.rgReaderStates)
1563 {
1564 free(states);
1565 return STATUS_NO_MEMORY;
1566 }
1567
1568 for (UINT32 i = 0; i < ret.cReaders; i++)
1569 {
1570 LPSCARD_READERSTATEA state = &states[i];
1571 ret.rgReaderStates[i].dwCurrentState = state->dwCurrentState;
1572 ret.rgReaderStates[i].dwEventState = state->dwEventState;
1573 ret.rgReaderStates[i].cbAtr = state->cbAtr;
1574 CopyMemory(&(ret.rgReaderStates[i].rgbAtr), &(state->rgbAtr),
1575 sizeof(ret.rgReaderStates[i].rgbAtr));
1576 }
1577
1578 free(states);
1579
1580 status = smartcard_pack_get_status_change_return(out, &ret, FALSE);
1581
1582 free(ret.rgReaderStates);
1583 if (status != SCARD_S_SUCCESS)
1584 return status;
1585 return ret.ReturnCode;
1586}
1587
1588LONG smartcard_irp_device_control_call(scard_call_context* smartcard, wStream* out,
1589 NTSTATUS* pIoStatus, SMARTCARD_OPERATION* operation)
1590{
1591 LONG result = 0;
1592 UINT32 offset = 0;
1593 size_t objectBufferLength = 0;
1594
1595 WINPR_ASSERT(smartcard);
1596 WINPR_ASSERT(out);
1597 WINPR_ASSERT(pIoStatus);
1598 WINPR_ASSERT(operation);
1599
1600 const UINT32 ioControlCode = operation->ioControlCode;
1608 const size_t outMaxLen = MAX(2048, operation->outputBufferLength);
1609 if (!Stream_EnsureRemainingCapacity(out, outMaxLen))
1610 return SCARD_E_NO_MEMORY;
1611
1612 /* Device Control Response */
1613 Stream_Write_UINT32(out, 0); /* OutputBufferLength (4 bytes) */
1614 Stream_Zero(out, SMARTCARD_COMMON_TYPE_HEADER_LENGTH); /* CommonTypeHeader (8 bytes) */
1615 Stream_Zero(out, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH); /* PrivateTypeHeader (8 bytes) */
1616 Stream_Write_UINT32(out, 0); /* Result (4 bytes) */
1617
1618 /* Call */
1619 switch (ioControlCode)
1620 {
1621 case SCARD_IOCTL_ESTABLISHCONTEXT:
1622 result = smartcard_EstablishContext_Call(smartcard, out, operation);
1623 break;
1624
1625 case SCARD_IOCTL_RELEASECONTEXT:
1626 result = smartcard_ReleaseContext_Call(smartcard, out, operation);
1627 break;
1628
1629 case SCARD_IOCTL_ISVALIDCONTEXT:
1630 result = smartcard_IsValidContext_Call(smartcard, out, operation);
1631 break;
1632
1633 case SCARD_IOCTL_LISTREADERGROUPSA:
1634 result = smartcard_ListReaderGroupsA_Call(smartcard, out, operation);
1635 break;
1636
1637 case SCARD_IOCTL_LISTREADERGROUPSW:
1638 result = smartcard_ListReaderGroupsW_Call(smartcard, out, operation);
1639 break;
1640
1641 case SCARD_IOCTL_LISTREADERSA:
1642 result = smartcard_ListReadersA_Call(smartcard, out, operation);
1643 break;
1644
1645 case SCARD_IOCTL_LISTREADERSW:
1646 result = smartcard_ListReadersW_Call(smartcard, out, operation);
1647 break;
1648
1649 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1650 result = smartcard_IntroduceReaderGroupA_Call(smartcard, out, operation);
1651 break;
1652
1653 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1654 result = smartcard_IntroduceReaderGroupW_Call(smartcard, out, operation);
1655 break;
1656
1657 case SCARD_IOCTL_FORGETREADERGROUPA:
1658 result = smartcard_ForgetReaderA_Call(smartcard, out, operation);
1659 break;
1660
1661 case SCARD_IOCTL_FORGETREADERGROUPW:
1662 result = smartcard_ForgetReaderW_Call(smartcard, out, operation);
1663 break;
1664
1665 case SCARD_IOCTL_INTRODUCEREADERA:
1666 result = smartcard_IntroduceReaderA_Call(smartcard, out, operation);
1667 break;
1668
1669 case SCARD_IOCTL_INTRODUCEREADERW:
1670 result = smartcard_IntroduceReaderW_Call(smartcard, out, operation);
1671 break;
1672
1673 case SCARD_IOCTL_FORGETREADERA:
1674 result = smartcard_ForgetReaderA_Call(smartcard, out, operation);
1675 break;
1676
1677 case SCARD_IOCTL_FORGETREADERW:
1678 result = smartcard_ForgetReaderW_Call(smartcard, out, operation);
1679 break;
1680
1681 case SCARD_IOCTL_ADDREADERTOGROUPA:
1682 result = smartcard_AddReaderToGroupA_Call(smartcard, out, operation);
1683 break;
1684
1685 case SCARD_IOCTL_ADDREADERTOGROUPW:
1686 result = smartcard_AddReaderToGroupW_Call(smartcard, out, operation);
1687 break;
1688
1689 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1690 result = smartcard_RemoveReaderFromGroupA_Call(smartcard, out, operation);
1691 break;
1692
1693 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1694 result = smartcard_RemoveReaderFromGroupW_Call(smartcard, out, operation);
1695 break;
1696
1697 case SCARD_IOCTL_LOCATECARDSA:
1698 result = smartcard_LocateCardsA_Call(smartcard, out, operation);
1699 break;
1700
1701 case SCARD_IOCTL_LOCATECARDSW:
1702 result = smartcard_LocateCardsW_Call(smartcard, out, operation);
1703 break;
1704
1705 case SCARD_IOCTL_GETSTATUSCHANGEA:
1706 result = smartcard_GetStatusChangeA_Call(smartcard, out, operation);
1707 break;
1708
1709 case SCARD_IOCTL_GETSTATUSCHANGEW:
1710 result = smartcard_GetStatusChangeW_Call(smartcard, out, operation);
1711 break;
1712
1713 case SCARD_IOCTL_CANCEL:
1714 result = smartcard_Cancel_Call(smartcard, out, operation);
1715 break;
1716
1717 case SCARD_IOCTL_CONNECTA:
1718 result = smartcard_ConnectA_Call(smartcard, out, operation);
1719 break;
1720
1721 case SCARD_IOCTL_CONNECTW:
1722 result = smartcard_ConnectW_Call(smartcard, out, operation);
1723 break;
1724
1725 case SCARD_IOCTL_RECONNECT:
1726 result = smartcard_Reconnect_Call(smartcard, out, operation);
1727 break;
1728
1729 case SCARD_IOCTL_DISCONNECT:
1730 result = smartcard_Disconnect_Call(smartcard, out, operation);
1731 break;
1732
1733 case SCARD_IOCTL_BEGINTRANSACTION:
1734 result = smartcard_BeginTransaction_Call(smartcard, out, operation);
1735 break;
1736
1737 case SCARD_IOCTL_ENDTRANSACTION:
1738 result = smartcard_EndTransaction_Call(smartcard, out, operation);
1739 break;
1740
1741 case SCARD_IOCTL_STATE:
1742 result = smartcard_State_Call(smartcard, out, operation);
1743 break;
1744
1745 case SCARD_IOCTL_STATUSA:
1746 result = smartcard_StatusA_Call(smartcard, out, operation);
1747 break;
1748
1749 case SCARD_IOCTL_STATUSW:
1750 result = smartcard_StatusW_Call(smartcard, out, operation);
1751 break;
1752
1753 case SCARD_IOCTL_TRANSMIT:
1754 result = smartcard_Transmit_Call(smartcard, out, operation);
1755 break;
1756
1757 case SCARD_IOCTL_CONTROL:
1758 result = smartcard_Control_Call(smartcard, out, operation);
1759 break;
1760
1761 case SCARD_IOCTL_GETATTRIB:
1762 result = smartcard_GetAttrib_Call(smartcard, out, operation);
1763 break;
1764
1765 case SCARD_IOCTL_SETATTRIB:
1766 result = smartcard_SetAttrib_Call(smartcard, out, operation);
1767 break;
1768
1769 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
1770 result = smartcard_AccessStartedEvent_Call(smartcard, out, operation);
1771 break;
1772
1773 case SCARD_IOCTL_LOCATECARDSBYATRA:
1774 result = smartcard_LocateCardsByATRA_Call(smartcard, out, operation);
1775 break;
1776
1777 case SCARD_IOCTL_LOCATECARDSBYATRW:
1778 result = smartcard_LocateCardsW_Call(smartcard, out, operation);
1779 break;
1780
1781 case SCARD_IOCTL_READCACHEA:
1782 result = smartcard_ReadCacheA_Call(smartcard, out, operation);
1783 break;
1784
1785 case SCARD_IOCTL_READCACHEW:
1786 result = smartcard_ReadCacheW_Call(smartcard, out, operation);
1787 break;
1788
1789 case SCARD_IOCTL_WRITECACHEA:
1790 result = smartcard_WriteCacheA_Call(smartcard, out, operation);
1791 break;
1792
1793 case SCARD_IOCTL_WRITECACHEW:
1794 result = smartcard_WriteCacheW_Call(smartcard, out, operation);
1795 break;
1796
1797 case SCARD_IOCTL_GETTRANSMITCOUNT:
1798 result = smartcard_GetTransmitCount_Call(smartcard, out, operation);
1799 break;
1800
1801 case SCARD_IOCTL_RELEASETARTEDEVENT:
1802 result = smartcard_ReleaseStartedEvent_Call(smartcard, out, operation);
1803 break;
1804
1805 case SCARD_IOCTL_GETREADERICON:
1806 result = smartcard_GetReaderIcon_Call(smartcard, out, operation);
1807 break;
1808
1809 case SCARD_IOCTL_GETDEVICETYPEID:
1810 result = smartcard_GetDeviceTypeId_Call(smartcard, out, operation);
1811 break;
1812
1813 default:
1814 result = STATUS_UNSUCCESSFUL;
1815 break;
1816 }
1817
1824 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
1825 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
1826 {
1827 offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
1828 smartcard_pack_write_size_align(out, Stream_GetPosition(out) - offset, 8);
1829 }
1830
1831 if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
1832 (result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE) &&
1833 (result != SCARD_W_CACHE_ITEM_NOT_FOUND) && (result != SCARD_W_CACHE_ITEM_STALE))
1834 {
1835 WLog_Print(smartcard->log, WLOG_WARN,
1836 "IRP failure: %s (0x%08" PRIX32 "), status: %s (0x%08" PRIX32 ")",
1837 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
1838 SCardGetErrorString(result), result);
1839 }
1840
1841 *pIoStatus = STATUS_SUCCESS;
1842
1843 if ((result & 0xC0000000L) == 0xC0000000L)
1844 {
1845 /* NTSTATUS error */
1846 *pIoStatus = result;
1847 WLog_Print(smartcard->log, WLOG_WARN,
1848 "IRP failure: %s (0x%08" PRIX32 "), ntstatus: 0x%08" PRIX32 "",
1849 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, result);
1850 }
1851
1852 Stream_SealLength(out);
1853 size_t outputBufferLength = Stream_Length(out);
1854 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1855 outputBufferLength -= (RDPDR_DEVICE_IO_RESPONSE_LENGTH + 4U);
1856 WINPR_ASSERT(outputBufferLength >= RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1857 objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
1858 WINPR_ASSERT(outputBufferLength <= UINT32_MAX);
1859 WINPR_ASSERT(objectBufferLength <= UINT32_MAX);
1860 Stream_SetPosition(out, RDPDR_DEVICE_IO_RESPONSE_LENGTH);
1861
1862 /* [MS-RDPESC] 3.2.5.2 Processing Incoming Replies
1863 *
1864 * if the output buffer is too small, reply with STATUS_BUFFER_TOO_SMALL
1865 * and a outputBufferLength of 0.
1866 * The message should then be retransmitted from the server with a doubled
1867 * buffer size.
1868 */
1869 if (outputBufferLength > operation->outputBufferLength)
1870 {
1871 WLog_Print(smartcard->log, WLOG_WARN,
1872 "IRP warn: expected outputBufferLength %" PRIu32 ", but current limit %" PRIu32
1873 ", respond with STATUS_BUFFER_TOO_SMALL",
1874 operation->outputBufferLength, outputBufferLength);
1875
1876 *pIoStatus = STATUS_BUFFER_TOO_SMALL;
1877 result = *pIoStatus;
1878 outputBufferLength = 0;
1879 objectBufferLength = 0;
1880 }
1881
1882 /* Device Control Response */
1883 Stream_Write_UINT32(out, (UINT32)outputBufferLength); /* OutputBufferLength (4 bytes) */
1884 smartcard_pack_common_type_header(out); /* CommonTypeHeader (8 bytes) */
1885 smartcard_pack_private_type_header(
1886 out, (UINT32)objectBufferLength); /* PrivateTypeHeader (8 bytes) */
1887 Stream_Write_INT32(out, result); /* Result (4 bytes) */
1888 Stream_SetPosition(out, Stream_Length(out));
1889 return SCARD_S_SUCCESS;
1890}
1891
1892void context_free(void* arg)
1893{
1894 struct s_scard_context_element* element = arg;
1895 if (!arg)
1896 return;
1897
1898 if (element->fn_free)
1899 element->fn_free(element->context);
1900 free(element);
1901}
1902
1903scard_call_context* smartcard_call_context_new(const rdpSettings* settings)
1904{
1905 wObject* obj = NULL;
1906 scard_call_context* ctx = NULL;
1907
1908 WINPR_ASSERT(settings);
1909 ctx = calloc(1, sizeof(scard_call_context));
1910 if (!ctx)
1911 goto fail;
1912
1913 ctx->log = WLog_Get(SCARD_TAG);
1914 WINPR_ASSERT(ctx->log);
1915
1916 ctx->stopEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
1917 if (!ctx->stopEvent)
1918 goto fail;
1919
1920 ctx->names = LinkedList_New();
1921 if (!ctx->names)
1922 goto fail;
1923
1924#if defined(WITH_SMARTCARD_EMULATE)
1925 ctx->useEmulatedCard = freerdp_settings_get_bool(settings, FreeRDP_SmartcardEmulation);
1926#endif
1927
1928 if (ctx->useEmulatedCard)
1929 {
1930#if defined(WITH_SMARTCARD_EMULATE)
1931 ctx->emulation = Emulate_New(settings);
1932 if (!ctx->emulation)
1933 goto fail;
1934#else
1935 WLog_Print(ctx->log, WLOG_ERROR, "Smartcard emulation requested, but not supported!");
1936 goto fail;
1937#endif
1938 }
1939 else
1940 {
1941 const char* WinSCardModule = freerdp_settings_get_string(settings, FreeRDP_WinSCardModule);
1942 if (WinSCardModule)
1943 {
1944 ctx->hWinSCardLibrary = LoadLibraryX(WinSCardModule);
1945
1946 if (!ctx->hWinSCardLibrary)
1947 {
1948 WLog_Print(ctx->log, WLOG_ERROR, "Failed to load WinSCard library: '%s'",
1949 WinSCardModule);
1950 goto fail;
1951 }
1952
1953 if (!WinSCard_LoadApiTableFunctions(&ctx->WinSCardApi, ctx->hWinSCardLibrary))
1954 goto fail;
1955 ctx->pWinSCardApi = &ctx->WinSCardApi;
1956 }
1957 else
1958 {
1959 ctx->pWinSCardApi = WinPR_GetSCardApiFunctionTable();
1960 }
1961
1962 if (!ctx->pWinSCardApi)
1963 {
1964 WLog_Print(ctx->log, WLOG_ERROR, "Failed to load WinSCard API!");
1965 goto fail;
1966 }
1967 }
1968
1969 ctx->rgSCardContextList = HashTable_New(FALSE);
1970 if (!ctx->rgSCardContextList)
1971 goto fail;
1972
1973 obj = HashTable_ValueObject(ctx->rgSCardContextList);
1974 WINPR_ASSERT(obj);
1975 obj->fnObjectFree = context_free;
1976
1977 return ctx;
1978fail:
1979 WINPR_PRAGMA_DIAG_PUSH
1980 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1981 smartcard_call_context_free(ctx);
1982 WINPR_PRAGMA_DIAG_POP
1983 return NULL;
1984}
1985
1986void smartcard_call_context_free(scard_call_context* ctx)
1987{
1988 if (!ctx)
1989 return;
1990
1991 smartcard_call_context_signal_stop(ctx, FALSE);
1992
1993 LinkedList_Free(ctx->names);
1994 if (ctx->StartedEvent)
1995 {
1996 WINPR_ASSERT(ctx->useEmulatedCard || ctx->pWinSCardApi);
1997 wrap(ctx, SCardReleaseStartedEvent);
1998 }
1999
2000 if (ctx->useEmulatedCard)
2001 {
2002#ifdef WITH_SMARTCARD_EMULATE
2003 if (ctx->emulation)
2004 {
2005 Emulate_Free(ctx->emulation);
2006 ctx->emulation = NULL;
2007 }
2008#endif
2009 }
2010
2011 if (ctx->hWinSCardLibrary)
2012 {
2013 ZeroMemory(&ctx->WinSCardApi, sizeof(SCardApiFunctionTable));
2014 FreeLibrary(ctx->hWinSCardLibrary);
2015 ctx->hWinSCardLibrary = NULL;
2016 }
2017
2018 ctx->pWinSCardApi = NULL;
2019
2020 HashTable_Free(ctx->rgSCardContextList);
2021 (void)CloseHandle(ctx->stopEvent);
2022 free(ctx);
2023}
2024
2025BOOL smartcard_call_context_add(scard_call_context* ctx, const char* name)
2026{
2027 WINPR_ASSERT(ctx);
2028 WINPR_ASSERT(name);
2029 return LinkedList_AddLast(ctx->names, name);
2030}
2031
2032BOOL smartcard_call_cancel_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2033{
2034 WINPR_ASSERT(ctx);
2035 if (wrap(ctx, SCardIsValidContext, hContext) == SCARD_S_SUCCESS)
2036 {
2037 wrap(ctx, SCardCancel, hContext);
2038 }
2039 return TRUE;
2040}
2041
2042BOOL smartcard_call_release_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2043{
2044 WINPR_ASSERT(ctx);
2045 wrap(ctx, SCardReleaseContext, hContext);
2046 return TRUE;
2047}
2048
2049BOOL smartcard_call_cancel_all_context(scard_call_context* ctx)
2050{
2051 WINPR_ASSERT(ctx);
2052
2053 HashTable_Clear(ctx->rgSCardContextList);
2054 return TRUE;
2055}
2056
2057BOOL smarcard_call_set_callbacks(scard_call_context* ctx, void* userdata,
2058 void* (*fn_new)(void*, SCARDCONTEXT), void (*fn_free)(void*))
2059{
2060 WINPR_ASSERT(ctx);
2061 ctx->userdata = userdata;
2062 ctx->fn_new = fn_new;
2063 ctx->fn_free = fn_free;
2064 return TRUE;
2065}
2066
2067void* smartcard_call_get_context(scard_call_context* ctx, SCARDCONTEXT hContext)
2068{
2069 struct s_scard_context_element* element = NULL;
2070
2071 WINPR_ASSERT(ctx);
2072 element = HashTable_GetItemValue(ctx->rgSCardContextList, (void*)hContext);
2073 if (!element)
2074 return NULL;
2075 return element->context;
2076}
2077
2078BOOL smartcard_call_is_configured(scard_call_context* ctx)
2079{
2080 WINPR_ASSERT(ctx);
2081
2082#if defined(WITH_SMARTCARD_EMULATE)
2083 if (ctx->useEmulatedCard)
2084 return Emulate_IsConfigured(ctx->emulation);
2085#endif
2086
2087 return FALSE;
2088}
2089
2090BOOL smartcard_call_context_signal_stop(scard_call_context* ctx, BOOL reset)
2091{
2092 WINPR_ASSERT(ctx);
2093 if (!ctx->stopEvent)
2094 return TRUE;
2095
2096 if (reset)
2097 return ResetEvent(ctx->stopEvent);
2098 else
2099 return SetEvent(ctx->stopEvent);
2100}
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