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