FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
smartcard_operations.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/smartcard.h>
34
35#include <freerdp/freerdp.h>
36#include <freerdp/channels/rdpdr.h>
37#include <freerdp/channels/scard.h>
38
39#include <freerdp/utils/rdpdr_utils.h>
40
41#include <freerdp/utils/smartcard_operations.h>
42#include <freerdp/utils/smartcard_pack.h>
43
44#include <freerdp/log.h>
45#define TAG FREERDP_TAG("utils.smartcard.ops")
46
47static LONG smartcard_call_to_operation_handle(SMARTCARD_OPERATION* operation)
48{
49 WINPR_ASSERT(operation);
50
51 operation->hContext =
52 smartcard_scard_context_native_from_redir(&(operation->call.handles.hContext));
53 operation->hCard = smartcard_scard_handle_native_from_redir(&(operation->call.handles.hCard));
54
55 return SCARD_S_SUCCESS;
56}
57
58static LONG smartcard_EstablishContext_Decode(wStream* s, SMARTCARD_OPERATION* operation)
59{
60 LONG status = 0;
61
62 WINPR_ASSERT(s);
63 WINPR_ASSERT(operation);
64
65 status = smartcard_unpack_establish_context_call(s, &operation->call.establishContext);
66 if (status != SCARD_S_SUCCESS)
67 {
68 return scard_log_status_error(TAG, "smartcard_unpack_establish_context_call", status);
69 }
70
71 return SCARD_S_SUCCESS;
72}
73
74static LONG smartcard_ReleaseContext_Decode(wStream* s, SMARTCARD_OPERATION* operation)
75{
76 LONG status = 0;
77
78 WINPR_ASSERT(s);
79 WINPR_ASSERT(operation);
80
81 status = smartcard_unpack_context_call(s, &operation->call.context, "ReleaseContext");
82 if (status != SCARD_S_SUCCESS)
83 scard_log_status_error(TAG, "smartcard_unpack_context_call", status);
84
85 return status;
86}
87
88static LONG smartcard_IsValidContext_Decode(wStream* s, SMARTCARD_OPERATION* operation)
89{
90 LONG status = 0;
91
92 WINPR_ASSERT(s);
93 WINPR_ASSERT(operation);
94
95 status = smartcard_unpack_context_call(s, &operation->call.context, "IsValidContext");
96
97 return status;
98}
99
100static LONG smartcard_ListReaderGroupsA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
101{
102 LONG status = 0;
103
104 WINPR_ASSERT(s);
105 WINPR_ASSERT(operation);
106
107 status = smartcard_unpack_list_reader_groups_call(s, &operation->call.listReaderGroups, FALSE);
108
109 return status;
110}
111
112static LONG smartcard_ListReaderGroupsW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
113{
114 LONG status = 0;
115
116 WINPR_ASSERT(s);
117 WINPR_ASSERT(operation);
118
119 status = smartcard_unpack_list_reader_groups_call(s, &operation->call.listReaderGroups, TRUE);
120
121 return status;
122}
123
124static LONG smartcard_ListReadersA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
125{
126 LONG status = 0;
127
128 WINPR_ASSERT(s);
129 WINPR_ASSERT(operation);
130
131 status = smartcard_unpack_list_readers_call(s, &operation->call.listReaders, FALSE);
132
133 return status;
134}
135
136static LONG smartcard_ListReadersW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
137{
138 LONG status = 0;
139
140 WINPR_ASSERT(s);
141 WINPR_ASSERT(operation);
142
143 status = smartcard_unpack_list_readers_call(s, &operation->call.listReaders, TRUE);
144
145 return status;
146}
147
148static LONG smartcard_context_and_two_strings_a_Decode(wStream* s, SMARTCARD_OPERATION* operation)
149{
150 LONG status = 0;
151
152 WINPR_ASSERT(s);
153 WINPR_ASSERT(operation);
154
155 status =
156 smartcard_unpack_context_and_two_strings_a_call(s, &operation->call.contextAndTwoStringA);
157
158 return status;
159}
160
161static LONG smartcard_context_and_two_strings_w_Decode(wStream* s, SMARTCARD_OPERATION* operation)
162{
163 LONG status = 0;
164
165 WINPR_ASSERT(s);
166 WINPR_ASSERT(operation);
167
168 status =
169 smartcard_unpack_context_and_two_strings_w_call(s, &operation->call.contextAndTwoStringW);
170
171 return status;
172}
173
174static LONG smartcard_context_and_string_a_Decode(wStream* s, SMARTCARD_OPERATION* operation)
175{
176 LONG status = 0;
177
178 WINPR_ASSERT(s);
179 WINPR_ASSERT(operation);
180
181 status = smartcard_unpack_context_and_string_a_call(s, &operation->call.contextAndStringA);
182
183 return status;
184}
185
186static LONG smartcard_context_and_string_w_Decode(wStream* s, SMARTCARD_OPERATION* operation)
187{
188 LONG status = 0;
189
190 WINPR_ASSERT(s);
191 WINPR_ASSERT(operation);
192
193 status = smartcard_unpack_context_and_string_w_call(s, &operation->call.contextAndStringW);
194
195 return status;
196}
197
198static LONG smartcard_LocateCardsA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
199{
200 LONG status = 0;
201
202 WINPR_ASSERT(s);
203 WINPR_ASSERT(operation);
204
205 status = smartcard_unpack_locate_cards_a_call(s, &operation->call.locateCardsA);
206
207 return status;
208}
209
210static LONG smartcard_LocateCardsW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
211{
212 LONG status = 0;
213
214 WINPR_ASSERT(s);
215 WINPR_ASSERT(operation);
216
217 status = smartcard_unpack_locate_cards_w_call(s, &operation->call.locateCardsW);
218
219 return status;
220}
221
222static LONG smartcard_GetStatusChangeA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
223{
224 LONG status = 0;
225
226 WINPR_ASSERT(s);
227 WINPR_ASSERT(operation);
228
229 status = smartcard_unpack_get_status_change_a_call(s, &operation->call.getStatusChangeA);
230
231 return status;
232}
233
234static LONG smartcard_GetStatusChangeW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
235{
236 LONG status = 0;
237
238 WINPR_ASSERT(s);
239 WINPR_ASSERT(operation);
240
241 status = smartcard_unpack_get_status_change_w_call(s, &operation->call.getStatusChangeW);
242
243 return status;
244}
245
246static LONG smartcard_Cancel_Decode(wStream* s, SMARTCARD_OPERATION* operation)
247{
248 LONG status = 0;
249
250 WINPR_ASSERT(s);
251 WINPR_ASSERT(operation);
252
253 status = smartcard_unpack_context_call(s, &operation->call.context, "Cancel");
254
255 return status;
256}
257
258static LONG smartcard_ConnectA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
259{
260 LONG status = 0;
261
262 WINPR_ASSERT(s);
263 WINPR_ASSERT(operation);
264
265 status = smartcard_unpack_connect_a_call(s, &operation->call.connectA);
266
267 return status;
268}
269
270static LONG smartcard_ConnectW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
271{
272 LONG status = 0;
273
274 WINPR_ASSERT(s);
275 WINPR_ASSERT(operation);
276
277 status = smartcard_unpack_connect_w_call(s, &operation->call.connectW);
278
279 return status;
280}
281
282static LONG smartcard_Reconnect_Decode(wStream* s, SMARTCARD_OPERATION* operation)
283{
284 LONG status = 0;
285
286 WINPR_ASSERT(s);
287 WINPR_ASSERT(operation);
288
289 status = smartcard_unpack_reconnect_call(s, &operation->call.reconnect);
290
291 return status;
292}
293
294static LONG smartcard_Disconnect_Decode(wStream* s, SMARTCARD_OPERATION* operation)
295{
296 LONG status = 0;
297
298 WINPR_ASSERT(s);
299 WINPR_ASSERT(operation);
300
301 status = smartcard_unpack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
302 "Disconnect");
303
304 return status;
305}
306
307static LONG smartcard_BeginTransaction_Decode(wStream* s, SMARTCARD_OPERATION* operation)
308{
309 LONG status = 0;
310
311 WINPR_ASSERT(s);
312 WINPR_ASSERT(operation);
313
314 status = smartcard_unpack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
315 "BeginTransaction");
316
317 return status;
318}
319
320static LONG smartcard_EndTransaction_Decode(wStream* s, SMARTCARD_OPERATION* operation)
321{
322 LONG status = 0;
323
324 WINPR_ASSERT(s);
325 WINPR_ASSERT(operation);
326
327 status = smartcard_unpack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
328 "EndTransaction");
329
330 return status;
331}
332
333static LONG smartcard_State_Decode(wStream* s, SMARTCARD_OPERATION* operation)
334{
335 LONG status = 0;
336
337 WINPR_ASSERT(s);
338 WINPR_ASSERT(operation);
339
340 status = smartcard_unpack_state_call(s, &operation->call.state);
341
342 return status;
343}
344
345static LONG smartcard_StatusA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
346{
347 LONG status = 0;
348
349 WINPR_ASSERT(s);
350 WINPR_ASSERT(operation);
351
352 status = smartcard_unpack_status_call(s, &operation->call.status, FALSE);
353
354 return status;
355}
356
357static LONG smartcard_StatusW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
358{
359 LONG status = 0;
360
361 WINPR_ASSERT(s);
362 WINPR_ASSERT(operation);
363
364 status = smartcard_unpack_status_call(s, &operation->call.status, TRUE);
365
366 return status;
367}
368
369static LONG smartcard_Transmit_Decode(wStream* s, SMARTCARD_OPERATION* operation)
370{
371 LONG status = 0;
372
373 WINPR_ASSERT(s);
374 WINPR_ASSERT(operation);
375
376 status = smartcard_unpack_transmit_call(s, &operation->call.transmit);
377
378 return status;
379}
380
381static LONG smartcard_Control_Decode(wStream* s, SMARTCARD_OPERATION* operation)
382{
383 LONG status = 0;
384
385 WINPR_ASSERT(s);
386 WINPR_ASSERT(operation);
387
388 status = smartcard_unpack_control_call(s, &operation->call.control);
389
390 return status;
391}
392
393static LONG smartcard_GetAttrib_Decode(wStream* s, SMARTCARD_OPERATION* operation)
394{
395 LONG status = 0;
396
397 WINPR_ASSERT(s);
398 WINPR_ASSERT(operation);
399
400 status = smartcard_unpack_get_attrib_call(s, &operation->call.getAttrib);
401
402 return status;
403}
404
405static LONG smartcard_SetAttrib_Decode(wStream* s, SMARTCARD_OPERATION* operation)
406{
407 LONG status = 0;
408
409 WINPR_ASSERT(s);
410 WINPR_ASSERT(operation);
411
412 status = smartcard_unpack_set_attrib_call(s, &operation->call.setAttrib);
413
414 return status;
415}
416
417static LONG smartcard_AccessStartedEvent_Decode(wStream* s, SMARTCARD_OPERATION* operation)
418{
419 WINPR_ASSERT(s);
420 WINPR_ASSERT(operation);
421
422 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
423 return SCARD_F_INTERNAL_ERROR;
424
425 Stream_Read_INT32(s, operation->call.lng.LongValue); /* Unused (4 bytes) */
426
427 return SCARD_S_SUCCESS;
428}
429
430static LONG smartcard_LocateCardsByATRA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
431{
432 LONG status = 0;
433
434 WINPR_ASSERT(s);
435 WINPR_ASSERT(operation);
436
437 status = smartcard_unpack_locate_cards_by_atr_a_call(s, &operation->call.locateCardsByATRA);
438
439 return status;
440}
441
442static LONG smartcard_LocateCardsByATRW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
443{
444 LONG status = 0;
445
446 WINPR_ASSERT(s);
447 WINPR_ASSERT(operation);
448
449 status = smartcard_unpack_locate_cards_by_atr_w_call(s, &operation->call.locateCardsByATRW);
450
451 return status;
452}
453
454static LONG smartcard_ReadCacheA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
455{
456 LONG status = 0;
457
458 WINPR_ASSERT(s);
459 WINPR_ASSERT(operation);
460
461 status = smartcard_unpack_read_cache_a_call(s, &operation->call.readCacheA);
462
463 return status;
464}
465
466static LONG smartcard_ReadCacheW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
467{
468 LONG status = 0;
469
470 WINPR_ASSERT(s);
471 WINPR_ASSERT(operation);
472
473 status = smartcard_unpack_read_cache_w_call(s, &operation->call.readCacheW);
474
475 return status;
476}
477
478static LONG smartcard_WriteCacheA_Decode(wStream* s, SMARTCARD_OPERATION* operation)
479{
480 LONG status = 0;
481
482 WINPR_ASSERT(s);
483 WINPR_ASSERT(operation);
484
485 status = smartcard_unpack_write_cache_a_call(s, &operation->call.writeCacheA);
486
487 return status;
488}
489
490static LONG smartcard_WriteCacheW_Decode(wStream* s, SMARTCARD_OPERATION* operation)
491{
492 LONG status = 0;
493
494 WINPR_ASSERT(s);
495 WINPR_ASSERT(operation);
496
497 status = smartcard_unpack_write_cache_w_call(s, &operation->call.writeCacheW);
498
499 return status;
500}
501
502static LONG smartcard_GetTransmitCount_Decode(wStream* s, SMARTCARD_OPERATION* operation)
503{
504 LONG status = 0;
505
506 WINPR_ASSERT(s);
507 WINPR_ASSERT(operation);
508
509 status = smartcard_unpack_get_transmit_count_call(s, &operation->call.getTransmitCount);
510
511 return status;
512}
513
514static LONG smartcard_ReleaseStartedEvent_Decode(wStream* s, SMARTCARD_OPERATION* operation)
515{
516 WINPR_UNUSED(s);
517 WINPR_UNUSED(operation);
518 WLog_WARN(TAG, "According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
519 "SCARD_IOCTL_RELEASETARTEDEVENT is not supported");
520 return SCARD_E_UNSUPPORTED_FEATURE;
521}
522
523static LONG smartcard_GetReaderIcon_Decode(wStream* s, SMARTCARD_OPERATION* operation)
524{
525 LONG status = 0;
526
527 WINPR_ASSERT(s);
528 WINPR_ASSERT(operation);
529
530 status = smartcard_unpack_get_reader_icon_call(s, &operation->call.getReaderIcon);
531
532 return status;
533}
534
535static LONG smartcard_GetDeviceTypeId_Decode(wStream* s, SMARTCARD_OPERATION* operation)
536{
537 LONG status = 0;
538
539 WINPR_ASSERT(s);
540 WINPR_ASSERT(operation);
541
542 status = smartcard_unpack_get_device_type_id_call(s, &operation->call.getDeviceTypeId);
543
544 return status;
545}
546
547LONG smartcard_irp_device_control_decode(wStream* s, UINT32 CompletionId, UINT32 FileId,
548 SMARTCARD_OPERATION* operation)
549{
550 LONG status = 0;
551 UINT32 offset = 0;
552
553 WINPR_ASSERT(s);
554 WINPR_ASSERT(operation);
555
556 /* Device Control Request */
557
558 if (!Stream_CheckAndLogRequiredLength(TAG, s, 32))
559 return SCARD_F_INTERNAL_ERROR;
560
561 const UINT32 outputBufferLength = Stream_Get_UINT32(s); /* OutputBufferLength (4 bytes) */
562 const UINT32 inputBufferLength = Stream_Get_UINT32(s); /* InputBufferLength (4 bytes) */
563 const UINT32 ioControlCode = Stream_Get_UINT32(s); /* IoControlCode (4 bytes) */
564 Stream_Seek(s, 20); /* Padding (20 bytes) */
565 operation->ioControlCode = ioControlCode;
566 operation->ioControlCodeName = scard_get_ioctl_string(ioControlCode, FALSE);
567 operation->outputBufferLength = outputBufferLength;
568
569 if (Stream_Length(s) != (Stream_GetPosition(s) + inputBufferLength))
570 {
571 WLog_WARN(TAG, "InputBufferLength mismatch: Actual: %" PRIuz " Expected: %" PRIuz "",
572 Stream_Length(s), Stream_GetPosition(s) + inputBufferLength);
573 return SCARD_F_INTERNAL_ERROR;
574 }
575
576 WLog_DBG(TAG, "%s (0x%08" PRIX32 ") FileId: %" PRIu32 " CompletionId: %" PRIu32 "",
577 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, FileId, CompletionId);
578
579 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
580 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
581 {
582 status = smartcard_unpack_common_type_header(s);
583 if (status != SCARD_S_SUCCESS)
584 return status;
585
586 status = smartcard_unpack_private_type_header(s);
587 if (status != SCARD_S_SUCCESS)
588 return status;
589 }
590
591 /* Decode */
592 switch (ioControlCode)
593 {
594 case SCARD_IOCTL_ESTABLISHCONTEXT:
595 status = smartcard_EstablishContext_Decode(s, operation);
596 break;
597
598 case SCARD_IOCTL_RELEASECONTEXT:
599 status = smartcard_ReleaseContext_Decode(s, operation);
600 break;
601
602 case SCARD_IOCTL_ISVALIDCONTEXT:
603 status = smartcard_IsValidContext_Decode(s, operation);
604 break;
605
606 case SCARD_IOCTL_LISTREADERGROUPSA:
607 status = smartcard_ListReaderGroupsA_Decode(s, operation);
608 break;
609
610 case SCARD_IOCTL_LISTREADERGROUPSW:
611 status = smartcard_ListReaderGroupsW_Decode(s, operation);
612 break;
613
614 case SCARD_IOCTL_LISTREADERSA:
615 status = smartcard_ListReadersA_Decode(s, operation);
616 break;
617
618 case SCARD_IOCTL_LISTREADERSW:
619 status = smartcard_ListReadersW_Decode(s, operation);
620 break;
621
622 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
623 status = smartcard_context_and_string_a_Decode(s, operation);
624 break;
625
626 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
627 status = smartcard_context_and_string_w_Decode(s, operation);
628 break;
629
630 case SCARD_IOCTL_FORGETREADERGROUPA:
631 status = smartcard_context_and_string_a_Decode(s, operation);
632 break;
633
634 case SCARD_IOCTL_FORGETREADERGROUPW:
635 status = smartcard_context_and_string_w_Decode(s, operation);
636 break;
637
638 case SCARD_IOCTL_INTRODUCEREADERA:
639 status = smartcard_context_and_two_strings_a_Decode(s, operation);
640 break;
641
642 case SCARD_IOCTL_INTRODUCEREADERW:
643 status = smartcard_context_and_two_strings_w_Decode(s, operation);
644 break;
645
646 case SCARD_IOCTL_FORGETREADERA:
647 status = smartcard_context_and_string_a_Decode(s, operation);
648 break;
649
650 case SCARD_IOCTL_FORGETREADERW:
651 status = smartcard_context_and_string_w_Decode(s, operation);
652 break;
653
654 case SCARD_IOCTL_ADDREADERTOGROUPA:
655 status = smartcard_context_and_two_strings_a_Decode(s, operation);
656 break;
657
658 case SCARD_IOCTL_ADDREADERTOGROUPW:
659 status = smartcard_context_and_two_strings_w_Decode(s, operation);
660 break;
661
662 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
663 status = smartcard_context_and_two_strings_a_Decode(s, operation);
664 break;
665
666 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
667 status = smartcard_context_and_two_strings_w_Decode(s, operation);
668 break;
669
670 case SCARD_IOCTL_LOCATECARDSA:
671 status = smartcard_LocateCardsA_Decode(s, operation);
672 break;
673
674 case SCARD_IOCTL_LOCATECARDSW:
675 status = smartcard_LocateCardsW_Decode(s, operation);
676 break;
677
678 case SCARD_IOCTL_GETSTATUSCHANGEA:
679 status = smartcard_GetStatusChangeA_Decode(s, operation);
680 break;
681
682 case SCARD_IOCTL_GETSTATUSCHANGEW:
683 status = smartcard_GetStatusChangeW_Decode(s, operation);
684 break;
685
686 case SCARD_IOCTL_CANCEL:
687 status = smartcard_Cancel_Decode(s, operation);
688 break;
689
690 case SCARD_IOCTL_CONNECTA:
691 status = smartcard_ConnectA_Decode(s, operation);
692 break;
693
694 case SCARD_IOCTL_CONNECTW:
695 status = smartcard_ConnectW_Decode(s, operation);
696 break;
697
698 case SCARD_IOCTL_RECONNECT:
699 status = smartcard_Reconnect_Decode(s, operation);
700 break;
701
702 case SCARD_IOCTL_DISCONNECT:
703 status = smartcard_Disconnect_Decode(s, operation);
704 break;
705
706 case SCARD_IOCTL_BEGINTRANSACTION:
707 status = smartcard_BeginTransaction_Decode(s, operation);
708 break;
709
710 case SCARD_IOCTL_ENDTRANSACTION:
711 status = smartcard_EndTransaction_Decode(s, operation);
712 break;
713
714 case SCARD_IOCTL_STATE:
715 status = smartcard_State_Decode(s, operation);
716 break;
717
718 case SCARD_IOCTL_STATUSA:
719 status = smartcard_StatusA_Decode(s, operation);
720 break;
721
722 case SCARD_IOCTL_STATUSW:
723 status = smartcard_StatusW_Decode(s, operation);
724 break;
725
726 case SCARD_IOCTL_TRANSMIT:
727 status = smartcard_Transmit_Decode(s, operation);
728 break;
729
730 case SCARD_IOCTL_CONTROL:
731 status = smartcard_Control_Decode(s, operation);
732 break;
733
734 case SCARD_IOCTL_GETATTRIB:
735 status = smartcard_GetAttrib_Decode(s, operation);
736 break;
737
738 case SCARD_IOCTL_SETATTRIB:
739 status = smartcard_SetAttrib_Decode(s, operation);
740 break;
741
742 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
743 status = smartcard_AccessStartedEvent_Decode(s, operation);
744 break;
745
746 case SCARD_IOCTL_LOCATECARDSBYATRA:
747 status = smartcard_LocateCardsByATRA_Decode(s, operation);
748 break;
749
750 case SCARD_IOCTL_LOCATECARDSBYATRW:
751 status = smartcard_LocateCardsByATRW_Decode(s, operation);
752 break;
753
754 case SCARD_IOCTL_READCACHEA:
755 status = smartcard_ReadCacheA_Decode(s, operation);
756 break;
757
758 case SCARD_IOCTL_READCACHEW:
759 status = smartcard_ReadCacheW_Decode(s, operation);
760 break;
761
762 case SCARD_IOCTL_WRITECACHEA:
763 status = smartcard_WriteCacheA_Decode(s, operation);
764 break;
765
766 case SCARD_IOCTL_WRITECACHEW:
767 status = smartcard_WriteCacheW_Decode(s, operation);
768 break;
769
770 case SCARD_IOCTL_GETTRANSMITCOUNT:
771 status = smartcard_GetTransmitCount_Decode(s, operation);
772 break;
773
774 case SCARD_IOCTL_RELEASETARTEDEVENT:
775 status = smartcard_ReleaseStartedEvent_Decode(s, operation);
776 break;
777
778 case SCARD_IOCTL_GETREADERICON:
779 status = smartcard_GetReaderIcon_Decode(s, operation);
780 break;
781
782 case SCARD_IOCTL_GETDEVICETYPEID:
783 status = smartcard_GetDeviceTypeId_Decode(s, operation);
784 break;
785
786 default:
787 status = SCARD_F_INTERNAL_ERROR;
788 break;
789 }
790
791 smartcard_call_to_operation_handle(operation);
792
793 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
794 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
795 {
796 offset = (RDPDR_DEVICE_IO_REQUEST_LENGTH + RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH);
797 smartcard_unpack_read_size_align(s, Stream_GetPosition(s) - offset, 8);
798 }
799
800 if (Stream_GetPosition(s) < Stream_Length(s))
801 {
802 size_t difference = 0;
803 difference = Stream_Length(s) - Stream_GetPosition(s);
804 WLog_WARN(TAG,
805 "IRP was not fully parsed %s (%s [0x%08" PRIX32 "]): Actual: %" PRIuz
806 ", Expected: %" PRIuz ", Difference: %" PRIuz "",
807 scard_get_ioctl_string(ioControlCode, TRUE),
808 scard_get_ioctl_string(ioControlCode, FALSE), ioControlCode,
809 Stream_GetPosition(s), Stream_Length(s), difference);
810 winpr_HexDump(TAG, WLOG_WARN, Stream_ConstPointer(s), difference);
811 }
812
813 if (Stream_GetPosition(s) > Stream_Length(s))
814 {
815 size_t difference = 0;
816 difference = Stream_GetPosition(s) - Stream_Length(s);
817 WLog_WARN(TAG,
818 "IRP was parsed beyond its end %s (0x%08" PRIX32 "): Actual: %" PRIuz
819 ", Expected: %" PRIuz ", Difference: %" PRIuz "",
820 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, Stream_GetPosition(s),
821 Stream_Length(s), difference);
822 }
823
824 return status;
825}
826
827static void free_reader_states_a(LPSCARD_READERSTATEA rgReaderStates, UINT32 cReaders)
828{
829 for (UINT32 x = 0; x < cReaders; x++)
830 {
831 SCARD_READERSTATEA* state = &rgReaderStates[x];
832 free(state->szReader);
833 }
834
835 free(rgReaderStates);
836}
837
838static void free_reader_states_w(LPSCARD_READERSTATEW rgReaderStates, UINT32 cReaders)
839{
840 for (UINT32 x = 0; x < cReaders; x++)
841 {
842 SCARD_READERSTATEW* state = &rgReaderStates[x];
843 free(state->szReader);
844 }
845
846 free(rgReaderStates);
847}
848
849void smartcard_operation_free(SMARTCARD_OPERATION* op, BOOL allocated)
850{
851 if (!op)
852 return;
853 switch (op->ioControlCode)
854 {
855 case SCARD_IOCTL_CANCEL:
856 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
857 case SCARD_IOCTL_RELEASETARTEDEVENT:
858 case SCARD_IOCTL_LISTREADERGROUPSA:
859 case SCARD_IOCTL_LISTREADERGROUPSW:
860 case SCARD_IOCTL_RECONNECT:
861 case SCARD_IOCTL_DISCONNECT:
862 case SCARD_IOCTL_BEGINTRANSACTION:
863 case SCARD_IOCTL_ENDTRANSACTION:
864 case SCARD_IOCTL_STATE:
865 case SCARD_IOCTL_STATUSA:
866 case SCARD_IOCTL_STATUSW:
867 case SCARD_IOCTL_ESTABLISHCONTEXT:
868 case SCARD_IOCTL_RELEASECONTEXT:
869 case SCARD_IOCTL_ISVALIDCONTEXT:
870 case SCARD_IOCTL_GETATTRIB:
871 case SCARD_IOCTL_GETTRANSMITCOUNT:
872 break;
873
874 case SCARD_IOCTL_LOCATECARDSA:
875 {
876 LocateCardsA_Call* call = &op->call.locateCardsA;
877 free(call->mszCards);
878
879 free_reader_states_a(call->rgReaderStates, call->cReaders);
880 }
881 break;
882 case SCARD_IOCTL_LOCATECARDSW:
883 {
884 LocateCardsW_Call* call = &op->call.locateCardsW;
885 free(call->mszCards);
886
887 free_reader_states_w(call->rgReaderStates, call->cReaders);
888 }
889 break;
890
891 case SCARD_IOCTL_LOCATECARDSBYATRA:
892 {
893 LocateCardsByATRA_Call* call = &op->call.locateCardsByATRA;
894
895 free_reader_states_a(call->rgReaderStates, call->cReaders);
896 }
897 break;
898 case SCARD_IOCTL_LOCATECARDSBYATRW:
899 {
900 LocateCardsByATRW_Call* call = &op->call.locateCardsByATRW;
901 free_reader_states_w(call->rgReaderStates, call->cReaders);
902 }
903 break;
904 case SCARD_IOCTL_FORGETREADERA:
905 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
906 case SCARD_IOCTL_FORGETREADERGROUPA:
907 {
908 ContextAndStringA_Call* call = &op->call.contextAndStringA;
909 free(call->sz);
910 }
911 break;
912
913 case SCARD_IOCTL_FORGETREADERW:
914 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
915 case SCARD_IOCTL_FORGETREADERGROUPW:
916 {
917 ContextAndStringW_Call* call = &op->call.contextAndStringW;
918 free(call->sz);
919 }
920 break;
921
922 case SCARD_IOCTL_INTRODUCEREADERA:
923 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
924 case SCARD_IOCTL_ADDREADERTOGROUPA:
925
926 {
927 ContextAndTwoStringA_Call* call = &op->call.contextAndTwoStringA;
928 free(call->sz1);
929 free(call->sz2);
930 }
931 break;
932
933 case SCARD_IOCTL_INTRODUCEREADERW:
934 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
935 case SCARD_IOCTL_ADDREADERTOGROUPW:
936
937 {
938 ContextAndTwoStringW_Call* call = &op->call.contextAndTwoStringW;
939 free(call->sz1);
940 free(call->sz2);
941 }
942 break;
943
944 case SCARD_IOCTL_LISTREADERSA:
945 case SCARD_IOCTL_LISTREADERSW:
946 {
947 ListReaders_Call* call = &op->call.listReaders;
948 free(call->mszGroups);
949 }
950 break;
951 case SCARD_IOCTL_GETSTATUSCHANGEA:
952 {
953 GetStatusChangeA_Call* call = &op->call.getStatusChangeA;
954 free_reader_states_a(call->rgReaderStates, call->cReaders);
955 }
956 break;
957
958 case SCARD_IOCTL_GETSTATUSCHANGEW:
959 {
960 GetStatusChangeW_Call* call = &op->call.getStatusChangeW;
961 free_reader_states_w(call->rgReaderStates, call->cReaders);
962 }
963 break;
964 case SCARD_IOCTL_GETREADERICON:
965 {
966 GetReaderIcon_Call* call = &op->call.getReaderIcon;
967 free(call->szReaderName);
968 }
969 break;
970 case SCARD_IOCTL_GETDEVICETYPEID:
971 {
972 GetDeviceTypeId_Call* call = &op->call.getDeviceTypeId;
973 free(call->szReaderName);
974 }
975 break;
976 case SCARD_IOCTL_CONNECTA:
977 {
978 ConnectA_Call* call = &op->call.connectA;
979 free(call->szReader);
980 }
981 break;
982 case SCARD_IOCTL_CONNECTW:
983 {
984 ConnectW_Call* call = &op->call.connectW;
985 free(call->szReader);
986 }
987 break;
988 case SCARD_IOCTL_SETATTRIB:
989 free(op->call.setAttrib.pbAttr);
990 break;
991 case SCARD_IOCTL_TRANSMIT:
992 {
993 Transmit_Call* call = &op->call.transmit;
994 free(call->pbSendBuffer);
995 free(call->pioSendPci);
996 free(call->pioRecvPci);
997 }
998 break;
999 case SCARD_IOCTL_CONTROL:
1000 {
1001 Control_Call* call = &op->call.control;
1002 free(call->pvInBuffer);
1003 }
1004 break;
1005 case SCARD_IOCTL_READCACHEA:
1006 {
1007 ReadCacheA_Call* call = &op->call.readCacheA;
1008 free(call->szLookupName);
1009 free(call->Common.CardIdentifier);
1010 }
1011 break;
1012 case SCARD_IOCTL_READCACHEW:
1013 {
1014 ReadCacheW_Call* call = &op->call.readCacheW;
1015 free(call->szLookupName);
1016 free(call->Common.CardIdentifier);
1017 }
1018 break;
1019 case SCARD_IOCTL_WRITECACHEA:
1020 {
1021 WriteCacheA_Call* call = &op->call.writeCacheA;
1022 free(call->szLookupName);
1023 free(call->Common.CardIdentifier);
1024 free(call->Common.pbData);
1025 }
1026 break;
1027 case SCARD_IOCTL_WRITECACHEW:
1028 {
1029 WriteCacheW_Call* call = &op->call.writeCacheW;
1030 free(call->szLookupName);
1031 free(call->Common.CardIdentifier);
1032 free(call->Common.pbData);
1033 }
1034 break;
1035 default:
1036 break;
1037 }
1038
1039 {
1040 SMARTCARD_OPERATION empty = { 0 };
1041 *op = empty;
1042 }
1043
1044 if (allocated)
1045 free(op);
1046}