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