FreeRDP
Loading...
Searching...
No Matches
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_request(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_request(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_request(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_request(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_request(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_request(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_request(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_ContextAndTwoStringA_decode_request(wStream* s,
149 SMARTCARD_OPERATION* operation)
150{
151 LONG status = 0;
152
153 WINPR_ASSERT(s);
154 WINPR_ASSERT(operation);
155
156 status =
157 smartcard_unpack_context_and_two_strings_a_call(s, &operation->call.contextAndTwoStringA);
158
159 return status;
160}
161
162static LONG smartcard_ContextAndTwoStringW_decode_request(wStream* s,
163 SMARTCARD_OPERATION* operation)
164{
165 LONG status = 0;
166
167 WINPR_ASSERT(s);
168 WINPR_ASSERT(operation);
169
170 status =
171 smartcard_unpack_context_and_two_strings_w_call(s, &operation->call.contextAndTwoStringW);
172
173 return status;
174}
175
176static LONG smartcard_ContextAndStringA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
177{
178 LONG status = 0;
179
180 WINPR_ASSERT(s);
181 WINPR_ASSERT(operation);
182
183 status = smartcard_unpack_context_and_string_a_call(s, &operation->call.contextAndStringA);
184
185 return status;
186}
187
188static LONG smartcard_ContextAndStringW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
189{
190 LONG status = 0;
191
192 WINPR_ASSERT(s);
193 WINPR_ASSERT(operation);
194
195 status = smartcard_unpack_context_and_string_w_call(s, &operation->call.contextAndStringW);
196
197 return status;
198}
199
200static LONG smartcard_LocateCardsA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
201{
202 LONG status = 0;
203
204 WINPR_ASSERT(s);
205 WINPR_ASSERT(operation);
206
207 status = smartcard_unpack_locate_cards_a_call(s, &operation->call.locateCardsA);
208
209 return status;
210}
211
212static LONG smartcard_LocateCardsW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
213{
214 LONG status = 0;
215
216 WINPR_ASSERT(s);
217 WINPR_ASSERT(operation);
218
219 status = smartcard_unpack_locate_cards_w_call(s, &operation->call.locateCardsW);
220
221 return status;
222}
223
224static LONG smartcard_GetStatusChangeA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
225{
226 WINPR_ASSERT(s);
227 WINPR_ASSERT(operation);
228
229 return smartcard_unpack_get_status_change_a_call(s, &operation->call.getStatusChangeA);
230}
231
232static LONG smartcard_GetStatusChangeW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
233{
234 WINPR_ASSERT(s);
235 WINPR_ASSERT(operation);
236
237 return smartcard_unpack_get_status_change_w_call(s, &operation->call.getStatusChangeW);
238}
239
240static LONG smartcard_Cancel_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
241{
242 LONG status = 0;
243
244 WINPR_ASSERT(s);
245 WINPR_ASSERT(operation);
246
247 status = smartcard_unpack_context_call(s, &operation->call.context, "Cancel");
248
249 return status;
250}
251
252static LONG smartcard_ConnectA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
253{
254 LONG status = 0;
255
256 WINPR_ASSERT(s);
257 WINPR_ASSERT(operation);
258
259 status = smartcard_unpack_connect_a_call(s, &operation->call.connectA);
260
261 return status;
262}
263
264static LONG smartcard_ConnectW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
265{
266 LONG status = 0;
267
268 WINPR_ASSERT(s);
269 WINPR_ASSERT(operation);
270
271 status = smartcard_unpack_connect_w_call(s, &operation->call.connectW);
272
273 return status;
274}
275
276static LONG smartcard_Reconnect_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
277{
278 LONG status = 0;
279
280 WINPR_ASSERT(s);
281 WINPR_ASSERT(operation);
282
283 status = smartcard_unpack_reconnect_call(s, &operation->call.reconnect);
284
285 return status;
286}
287
288static LONG smartcard_Disconnect_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
289{
290 LONG status = 0;
291
292 WINPR_ASSERT(s);
293 WINPR_ASSERT(operation);
294
295 status = smartcard_unpack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
296 "Disconnect");
297
298 return status;
299}
300
301static LONG smartcard_BeginTransaction_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
302{
303 LONG status = 0;
304
305 WINPR_ASSERT(s);
306 WINPR_ASSERT(operation);
307
308 status = smartcard_unpack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
309 "BeginTransaction");
310
311 return status;
312}
313
314static LONG smartcard_EndTransaction_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
315{
316 LONG status = 0;
317
318 WINPR_ASSERT(s);
319 WINPR_ASSERT(operation);
320
321 status = smartcard_unpack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
322 "EndTransaction");
323
324 return status;
325}
326
327static LONG smartcard_State_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
328{
329 LONG status = 0;
330
331 WINPR_ASSERT(s);
332 WINPR_ASSERT(operation);
333
334 status = smartcard_unpack_state_call(s, &operation->call.state);
335
336 return status;
337}
338
339static LONG smartcard_StatusA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
340{
341 LONG status = 0;
342
343 WINPR_ASSERT(s);
344 WINPR_ASSERT(operation);
345
346 status = smartcard_unpack_status_call(s, &operation->call.status, FALSE);
347
348 return status;
349}
350
351static LONG smartcard_StatusW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
352{
353 LONG status = 0;
354
355 WINPR_ASSERT(s);
356 WINPR_ASSERT(operation);
357
358 status = smartcard_unpack_status_call(s, &operation->call.status, TRUE);
359
360 return status;
361}
362
363static LONG smartcard_Transmit_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
364{
365 LONG status = 0;
366
367 WINPR_ASSERT(s);
368 WINPR_ASSERT(operation);
369
370 status = smartcard_unpack_transmit_call(s, &operation->call.transmit);
371
372 return status;
373}
374
375static LONG smartcard_Control_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
376{
377 LONG status = 0;
378
379 WINPR_ASSERT(s);
380 WINPR_ASSERT(operation);
381
382 status = smartcard_unpack_control_call(s, &operation->call.control);
383
384 return status;
385}
386
387static LONG smartcard_GetAttrib_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
388{
389 LONG status = 0;
390
391 WINPR_ASSERT(s);
392 WINPR_ASSERT(operation);
393
394 status = smartcard_unpack_get_attrib_call(s, &operation->call.getAttrib);
395
396 return status;
397}
398
399static LONG smartcard_SetAttrib_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
400{
401 LONG status = 0;
402
403 WINPR_ASSERT(s);
404 WINPR_ASSERT(operation);
405
406 status = smartcard_unpack_set_attrib_call(s, &operation->call.setAttrib);
407
408 return status;
409}
410
411static LONG smartcard_AccessStartedEvent_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
412{
413 WINPR_ASSERT(s);
414 WINPR_ASSERT(operation);
415
416 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
417 return SCARD_F_INTERNAL_ERROR;
418
419 Stream_Read_INT32(s, operation->call.lng.LongValue); /* Unused (4 bytes) */
420
421 return SCARD_S_SUCCESS;
422}
423
424static LONG smartcard_LocateCardsByATRA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
425{
426 LONG status = 0;
427
428 WINPR_ASSERT(s);
429 WINPR_ASSERT(operation);
430
431 status = smartcard_unpack_locate_cards_by_atr_a_call(s, &operation->call.locateCardsByATRA);
432
433 return status;
434}
435
436static LONG smartcard_LocateCardsByATRW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
437{
438 LONG status = 0;
439
440 WINPR_ASSERT(s);
441 WINPR_ASSERT(operation);
442
443 status = smartcard_unpack_locate_cards_by_atr_w_call(s, &operation->call.locateCardsByATRW);
444
445 return status;
446}
447
448static LONG smartcard_ReadCacheA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
449{
450 LONG status = 0;
451
452 WINPR_ASSERT(s);
453 WINPR_ASSERT(operation);
454
455 status = smartcard_unpack_read_cache_a_call(s, &operation->call.readCacheA);
456
457 return status;
458}
459
460static LONG smartcard_ReadCacheW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
461{
462 LONG status = 0;
463
464 WINPR_ASSERT(s);
465 WINPR_ASSERT(operation);
466
467 status = smartcard_unpack_read_cache_w_call(s, &operation->call.readCacheW);
468
469 return status;
470}
471
472static LONG smartcard_WriteCacheA_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
473{
474 LONG status = 0;
475
476 WINPR_ASSERT(s);
477 WINPR_ASSERT(operation);
478
479 status = smartcard_unpack_write_cache_a_call(s, &operation->call.writeCacheA);
480
481 return status;
482}
483
484static LONG smartcard_WriteCacheW_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
485{
486 LONG status = 0;
487
488 WINPR_ASSERT(s);
489 WINPR_ASSERT(operation);
490
491 status = smartcard_unpack_write_cache_w_call(s, &operation->call.writeCacheW);
492
493 return status;
494}
495
496static LONG smartcard_GetTransmitCount_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
497{
498 LONG status = 0;
499
500 WINPR_ASSERT(s);
501 WINPR_ASSERT(operation);
502
503 status = smartcard_unpack_get_transmit_count_call(s, &operation->call.getTransmitCount);
504
505 return status;
506}
507
508static LONG smartcard_ReleaseStartedEvent_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
509{
510 WINPR_UNUSED(s);
511 WINPR_UNUSED(operation);
512 WLog_WARN(TAG, "According to [MS-RDPESC] 3.1.4 Message Processing Events and Sequencing Rules "
513 "SCARD_IOCTL_RELEASETARTEDEVENT is not supported");
514 return SCARD_E_UNSUPPORTED_FEATURE;
515}
516
517static LONG smartcard_GetReaderIcon_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
518{
519 LONG status = 0;
520
521 WINPR_ASSERT(s);
522 WINPR_ASSERT(operation);
523
524 status = smartcard_unpack_get_reader_icon_call(s, &operation->call.getReaderIcon);
525
526 return status;
527}
528
529static LONG smartcard_GetDeviceTypeId_decode_request(wStream* s, SMARTCARD_OPERATION* operation)
530{
531 LONG status = 0;
532
533 WINPR_ASSERT(s);
534 WINPR_ASSERT(operation);
535
536 status = smartcard_unpack_get_device_type_id_call(s, &operation->call.getDeviceTypeId);
537
538 return status;
539}
540
541LONG smartcard_irp_device_control_decode(wStream* s, UINT32 CompletionId, UINT32 FileId,
542 SMARTCARD_OPERATION* operation)
543{
544 return smartcard_irp_device_control_decode_request(s, CompletionId, FileId, operation);
545}
546
547LONG smartcard_irp_device_control_decode_request(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, RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH))
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_request(s, operation);
596 break;
597
598 case SCARD_IOCTL_RELEASECONTEXT:
599 status = smartcard_ReleaseContext_decode_request(s, operation);
600 break;
601
602 case SCARD_IOCTL_ISVALIDCONTEXT:
603 status = smartcard_IsValidContext_decode_request(s, operation);
604 break;
605
606 case SCARD_IOCTL_LISTREADERGROUPSA:
607 status = smartcard_ListReaderGroupsA_decode_request(s, operation);
608 break;
609
610 case SCARD_IOCTL_LISTREADERGROUPSW:
611 status = smartcard_ListReaderGroupsW_decode_request(s, operation);
612 break;
613
614 case SCARD_IOCTL_LISTREADERSA:
615 status = smartcard_ListReadersA_decode_request(s, operation);
616 break;
617
618 case SCARD_IOCTL_LISTREADERSW:
619 status = smartcard_ListReadersW_decode_request(s, operation);
620 break;
621
622 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
623 status = smartcard_ContextAndStringA_decode_request(s, operation);
624 break;
625
626 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
627 status = smartcard_ContextAndStringW_decode_request(s, operation);
628 break;
629
630 case SCARD_IOCTL_FORGETREADERGROUPA:
631 status = smartcard_ContextAndStringA_decode_request(s, operation);
632 break;
633
634 case SCARD_IOCTL_FORGETREADERGROUPW:
635 status = smartcard_ContextAndStringW_decode_request(s, operation);
636 break;
637
638 case SCARD_IOCTL_INTRODUCEREADERA:
639 status = smartcard_ContextAndTwoStringA_decode_request(s, operation);
640 break;
641
642 case SCARD_IOCTL_INTRODUCEREADERW:
643 status = smartcard_ContextAndTwoStringW_decode_request(s, operation);
644 break;
645
646 case SCARD_IOCTL_FORGETREADERA:
647 status = smartcard_ContextAndStringA_decode_request(s, operation);
648 break;
649
650 case SCARD_IOCTL_FORGETREADERW:
651 status = smartcard_ContextAndStringW_decode_request(s, operation);
652 break;
653
654 case SCARD_IOCTL_ADDREADERTOGROUPA:
655 status = smartcard_ContextAndTwoStringA_decode_request(s, operation);
656 break;
657
658 case SCARD_IOCTL_ADDREADERTOGROUPW:
659 status = smartcard_ContextAndTwoStringW_decode_request(s, operation);
660 break;
661
662 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
663 status = smartcard_ContextAndTwoStringA_decode_request(s, operation);
664 break;
665
666 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
667 status = smartcard_ContextAndTwoStringW_decode_request(s, operation);
668 break;
669
670 case SCARD_IOCTL_LOCATECARDSA:
671 status = smartcard_LocateCardsA_decode_request(s, operation);
672 break;
673
674 case SCARD_IOCTL_LOCATECARDSW:
675 status = smartcard_LocateCardsW_decode_request(s, operation);
676 break;
677
678 case SCARD_IOCTL_GETSTATUSCHANGEA:
679 status = smartcard_GetStatusChangeA_decode_request(s, operation);
680 break;
681
682 case SCARD_IOCTL_GETSTATUSCHANGEW:
683 status = smartcard_GetStatusChangeW_decode_request(s, operation);
684 break;
685
686 case SCARD_IOCTL_CANCEL:
687 status = smartcard_Cancel_decode_request(s, operation);
688 break;
689
690 case SCARD_IOCTL_CONNECTA:
691 status = smartcard_ConnectA_decode_request(s, operation);
692 break;
693
694 case SCARD_IOCTL_CONNECTW:
695 status = smartcard_ConnectW_decode_request(s, operation);
696 break;
697
698 case SCARD_IOCTL_RECONNECT:
699 status = smartcard_Reconnect_decode_request(s, operation);
700 break;
701
702 case SCARD_IOCTL_DISCONNECT:
703 status = smartcard_Disconnect_decode_request(s, operation);
704 break;
705
706 case SCARD_IOCTL_BEGINTRANSACTION:
707 status = smartcard_BeginTransaction_decode_request(s, operation);
708 break;
709
710 case SCARD_IOCTL_ENDTRANSACTION:
711 status = smartcard_EndTransaction_decode_request(s, operation);
712 break;
713
714 case SCARD_IOCTL_STATE:
715 status = smartcard_State_decode_request(s, operation);
716 break;
717
718 case SCARD_IOCTL_STATUSA:
719 status = smartcard_StatusA_decode_request(s, operation);
720 break;
721
722 case SCARD_IOCTL_STATUSW:
723 status = smartcard_StatusW_decode_request(s, operation);
724 break;
725
726 case SCARD_IOCTL_TRANSMIT:
727 status = smartcard_Transmit_decode_request(s, operation);
728 break;
729
730 case SCARD_IOCTL_CONTROL:
731 status = smartcard_Control_decode_request(s, operation);
732 break;
733
734 case SCARD_IOCTL_GETATTRIB:
735 status = smartcard_GetAttrib_decode_request(s, operation);
736 break;
737
738 case SCARD_IOCTL_SETATTRIB:
739 status = smartcard_SetAttrib_decode_request(s, operation);
740 break;
741
742 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
743 status = smartcard_AccessStartedEvent_decode_request(s, operation);
744 break;
745
746 case SCARD_IOCTL_LOCATECARDSBYATRA:
747 status = smartcard_LocateCardsByATRA_decode_request(s, operation);
748 break;
749
750 case SCARD_IOCTL_LOCATECARDSBYATRW:
751 status = smartcard_LocateCardsByATRW_decode_request(s, operation);
752 break;
753
754 case SCARD_IOCTL_READCACHEA:
755 status = smartcard_ReadCacheA_decode_request(s, operation);
756 break;
757
758 case SCARD_IOCTL_READCACHEW:
759 status = smartcard_ReadCacheW_decode_request(s, operation);
760 break;
761
762 case SCARD_IOCTL_WRITECACHEA:
763 status = smartcard_WriteCacheA_decode_request(s, operation);
764 break;
765
766 case SCARD_IOCTL_WRITECACHEW:
767 status = smartcard_WriteCacheW_decode_request(s, operation);
768 break;
769
770 case SCARD_IOCTL_GETTRANSMITCOUNT:
771 status = smartcard_GetTransmitCount_decode_request(s, operation);
772 break;
773
774 case SCARD_IOCTL_RELEASETARTEDEVENT:
775 status = smartcard_ReleaseStartedEvent_decode_request(s, operation);
776 break;
777
778 case SCARD_IOCTL_GETREADERICON:
779 status = smartcard_GetReaderIcon_decode_request(s, operation);
780 break;
781
782 case SCARD_IOCTL_GETDEVICETYPEID:
783 status = smartcard_GetDeviceTypeId_decode_request(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 if (smartcard_unpack_read_size_align(s, Stream_GetPosition(s) - offset, 8) < 0)
798 return STATUS_INVALID_PARAMETER;
799 }
800
801 if (Stream_GetPosition(s) < Stream_Length(s))
802 {
803 size_t difference = 0;
804 difference = Stream_Length(s) - Stream_GetPosition(s);
805 WLog_WARN(TAG,
806 "IRP was not fully parsed %s (%s [0x%08" PRIX32 "]): Actual: %" PRIuz
807 ", Expected: %" PRIuz ", Difference: %" PRIuz "",
808 scard_get_ioctl_string(ioControlCode, TRUE),
809 scard_get_ioctl_string(ioControlCode, FALSE), ioControlCode,
810 Stream_GetPosition(s), Stream_Length(s), difference);
811 winpr_HexDump(TAG, WLOG_WARN, Stream_ConstPointer(s), difference);
812 }
813
814 if (Stream_GetPosition(s) > Stream_Length(s))
815 {
816 size_t difference = 0;
817 difference = Stream_GetPosition(s) - Stream_Length(s);
818 WLog_WARN(TAG,
819 "IRP was parsed beyond its end %s (0x%08" PRIX32 "): Actual: %" PRIuz
820 ", Expected: %" PRIuz ", Difference: %" PRIuz "",
821 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, Stream_GetPosition(s),
822 Stream_Length(s), difference);
823 }
824
825 return status;
826}
827
828static LONG smartcard_EstablishContext_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
829{
830 WINPR_ASSERT(s);
831 WINPR_ASSERT(operation);
832
833 return smartcard_unpack_establish_context_return(s, &operation->ret.establishContext);
834}
835
836static LONG smartcard_ReleaseContext_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
837{
838 WINPR_UNUSED(s);
839 WINPR_ASSERT(operation);
840
841 const Long_Return ret = { .ReturnCode = operation->returnCode };
842 smartcard_trace_long_return(&ret, "ReleaseContext");
843 return SCARD_S_SUCCESS;
844}
845
846static LONG smartcard_IsValidContext_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
847{
848 WINPR_UNUSED(s);
849 WINPR_ASSERT(operation);
850
851 const Long_Return ret = { .ReturnCode = operation->returnCode };
852 smartcard_trace_long_return(&ret, "IsValidContext");
853 return SCARD_S_SUCCESS;
854}
855
856static LONG smartcard_ListReaderGroupsA_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
857{
858 WINPR_ASSERT(s);
859 WINPR_ASSERT(operation);
860
861 return smartcard_unpack_list_reader_groups_return(s, &operation->ret.listReaders, FALSE);
862}
863
864static LONG smartcard_ListReaderGroupsW_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
865{
866 WINPR_ASSERT(s);
867 WINPR_ASSERT(operation);
868
869 return smartcard_unpack_list_reader_groups_return(s, &operation->ret.listReaders, TRUE);
870}
871
872static LONG smartcard_ListReadersA_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
873{
874 WINPR_ASSERT(s);
875 WINPR_ASSERT(operation);
876
877 return smartcard_unpack_list_readers_return(s, &operation->ret.listReaders, FALSE);
878}
879
880static LONG smartcard_ListReadersW_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
881{
882 WINPR_ASSERT(s);
883 WINPR_ASSERT(operation);
884
885 return smartcard_unpack_list_readers_return(s, &operation->ret.listReaders, TRUE);
886}
887
888static LONG smartcard_GetStatusChangeA_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
889{
890 WINPR_ASSERT(s);
891 WINPR_ASSERT(operation);
892
893 return smartcard_unpack_get_status_change_return(s, &operation->ret.getStatusChange, FALSE);
894}
895
896static LONG smartcard_GetStatusChangeW_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
897{
898 WINPR_ASSERT(s);
899 WINPR_ASSERT(operation);
900
901 return smartcard_unpack_get_status_change_return(s, &operation->ret.getStatusChange, TRUE);
902}
903
904static LONG smartcard_Cancel_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
905{
906 WINPR_UNUSED(s);
907 WINPR_ASSERT(operation);
908
909 const Long_Return ret = { .ReturnCode = operation->returnCode };
910 smartcard_trace_long_return(&ret, "Cancel");
911 return SCARD_S_SUCCESS;
912}
913
914static LONG smartcard_ConnectA_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
915{
916 WINPR_ASSERT(s);
917 WINPR_ASSERT(operation);
918
919 return smartcard_unpack_connect_return(s, &operation->ret.connect);
920}
921
922static LONG smartcard_ConnectW_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
923{
924 WINPR_ASSERT(s);
925 WINPR_ASSERT(operation);
926
927 return smartcard_unpack_connect_return(s, &operation->ret.connect);
928}
929
930static LONG smartcard_Reconnect_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
931{
932 WINPR_ASSERT(s);
933 WINPR_ASSERT(operation);
934
935 return smartcard_unpack_reconnect_return(s, &operation->ret.reconnect);
936}
937
938static LONG smartcard_Disconnect_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
939{
940 WINPR_UNUSED(s);
941 WINPR_ASSERT(operation);
942
943 const Long_Return ret = { .ReturnCode = operation->returnCode };
944 smartcard_trace_long_return(&ret, "Disconnect");
945 return SCARD_S_SUCCESS;
946}
947
948static LONG smartcard_BeginTransaction_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
949{
950 WINPR_UNUSED(s);
951 WINPR_ASSERT(operation);
952
953 const Long_Return ret = { .ReturnCode = operation->returnCode };
954 smartcard_trace_long_return(&ret, "BeginTransaction");
955 return SCARD_S_SUCCESS;
956}
957
958static LONG smartcard_EndTransaction_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
959{
960 WINPR_UNUSED(s);
961 WINPR_ASSERT(operation);
962
963 const Long_Return ret = { .ReturnCode = operation->returnCode };
964 smartcard_trace_long_return(&ret, "EndTransaction");
965 return SCARD_S_SUCCESS;
966}
967
968static LONG smartcard_StatusA_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
969{
970 WINPR_ASSERT(s);
971 WINPR_ASSERT(operation);
972
973 return smartcard_unpack_status_return(s, &operation->ret.status, FALSE);
974}
975
976static LONG smartcard_StatusW_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
977{
978 WINPR_ASSERT(s);
979 WINPR_ASSERT(operation);
980
981 return smartcard_unpack_status_return(s, &operation->ret.status, TRUE);
982}
983
984static LONG smartcard_Transmit_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
985{
986 WINPR_ASSERT(s);
987 WINPR_ASSERT(operation);
988
989 return smartcard_unpack_transmit_return(s, &operation->ret.transmit);
990}
991
992static LONG smartcard_Control_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
993{
994 WINPR_ASSERT(s);
995 WINPR_ASSERT(operation);
996
997 return smartcard_unpack_control_return(s, &operation->ret.control);
998}
999
1000static LONG smartcard_GetAttrib_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
1001{
1002 WINPR_ASSERT(s);
1003 WINPR_ASSERT(operation);
1004
1005 return smartcard_unpack_get_attrib_return(s, &operation->ret.getAttrib);
1006}
1007
1008static LONG smartcard_SetAttrib_decode_response(wStream* s, SMARTCARD_OPERATION* operation)
1009{
1010 WINPR_UNUSED(s);
1011 WINPR_ASSERT(operation);
1012
1013 const Long_Return ret = { .ReturnCode = operation->returnCode };
1014 smartcard_trace_long_return(&ret, "SetAttrib");
1015 return SCARD_S_SUCCESS;
1016}
1017
1018LONG smartcard_irp_device_control_decode_response(wStream* s, UINT32 ioControlCode,
1019 SMARTCARD_OPERATION* operation)
1020{
1021 LONG status = SCARD_S_SUCCESS;
1022
1023 WINPR_ASSERT(s);
1024 WINPR_ASSERT(operation);
1025
1026 if (!Stream_CheckAndLogRequiredLength(TAG, s, RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH))
1027 return SCARD_F_INTERNAL_ERROR;
1028
1029 const size_t startPosition = Stream_GetPosition(s);
1030
1031 const UINT32 outputBufferLength = Stream_Get_UINT32(s);
1032 operation->ioControlCode = ioControlCode;
1033 operation->ioControlCodeName = scard_get_ioctl_string(ioControlCode, FALSE);
1034 operation->outputBufferLength = outputBufferLength;
1035
1036 if (outputBufferLength == 0)
1037 return SCARD_S_SUCCESS;
1038
1039 if (!Stream_CheckAndLogRequiredLength(TAG, s, outputBufferLength))
1040 return SCARD_F_INTERNAL_ERROR;
1041
1042 status = smartcard_unpack_common_type_header(s);
1043 if (status != SCARD_S_SUCCESS)
1044 return status;
1045
1046 status = smartcard_unpack_private_type_header(s);
1047 if (status != SCARD_S_SUCCESS)
1048 return status;
1049
1050 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1051 return SCARD_F_INTERNAL_ERROR;
1052
1053 Stream_Read_INT32(s, operation->returnCode);
1054
1055 if (operation->returnCode != SCARD_S_SUCCESS)
1056 {
1057 WLog_DBG(TAG, "%s failed with ReturnCode %s [0x%08" PRIX32 "]",
1058 scard_get_ioctl_string(ioControlCode, TRUE),
1059 SCardGetErrorString(operation->returnCode), (UINT32)operation->returnCode);
1060 }
1061
1062 switch (ioControlCode)
1063 {
1064 case SCARD_IOCTL_ESTABLISHCONTEXT:
1065 status = smartcard_EstablishContext_decode_response(s, operation);
1066 break;
1067
1068 case SCARD_IOCTL_RELEASECONTEXT:
1069 status = smartcard_ReleaseContext_decode_response(s, operation);
1070 break;
1071
1072 case SCARD_IOCTL_ISVALIDCONTEXT:
1073 status = smartcard_IsValidContext_decode_response(s, operation);
1074 break;
1075
1076 case SCARD_IOCTL_LISTREADERGROUPSA:
1077 status = smartcard_ListReaderGroupsA_decode_response(s, operation);
1078 break;
1079
1080 case SCARD_IOCTL_LISTREADERGROUPSW:
1081 status = smartcard_ListReaderGroupsW_decode_response(s, operation);
1082 break;
1083
1084 case SCARD_IOCTL_LISTREADERSA:
1085 status = smartcard_ListReadersA_decode_response(s, operation);
1086 break;
1087
1088 case SCARD_IOCTL_LISTREADERSW:
1089 status = smartcard_ListReadersW_decode_response(s, operation);
1090 break;
1091
1092 case SCARD_IOCTL_GETSTATUSCHANGEA:
1093 status = smartcard_GetStatusChangeA_decode_response(s, operation);
1094 break;
1095
1096 case SCARD_IOCTL_GETSTATUSCHANGEW:
1097 status = smartcard_GetStatusChangeW_decode_response(s, operation);
1098 break;
1099
1100 case SCARD_IOCTL_CANCEL:
1101 status = smartcard_Cancel_decode_response(s, operation);
1102 break;
1103
1104 case SCARD_IOCTL_CONNECTA:
1105 status = smartcard_ConnectA_decode_response(s, operation);
1106 break;
1107
1108 case SCARD_IOCTL_CONNECTW:
1109 status = smartcard_ConnectW_decode_response(s, operation);
1110 break;
1111
1112 case SCARD_IOCTL_RECONNECT:
1113 status = smartcard_Reconnect_decode_response(s, operation);
1114 break;
1115
1116 case SCARD_IOCTL_DISCONNECT:
1117 status = smartcard_Disconnect_decode_response(s, operation);
1118 break;
1119
1120 case SCARD_IOCTL_BEGINTRANSACTION:
1121 status = smartcard_BeginTransaction_decode_response(s, operation);
1122 break;
1123
1124 case SCARD_IOCTL_ENDTRANSACTION:
1125 status = smartcard_EndTransaction_decode_response(s, operation);
1126 break;
1127
1128 case SCARD_IOCTL_STATUSA:
1129 status = smartcard_StatusA_decode_response(s, operation);
1130 break;
1131
1132 case SCARD_IOCTL_STATUSW:
1133 status = smartcard_StatusW_decode_response(s, operation);
1134 break;
1135
1136 case SCARD_IOCTL_TRANSMIT:
1137 status = smartcard_Transmit_decode_response(s, operation);
1138 break;
1139
1140 case SCARD_IOCTL_CONTROL:
1141 status = smartcard_Control_decode_response(s, operation);
1142 break;
1143
1144 case SCARD_IOCTL_GETATTRIB:
1145 status = smartcard_GetAttrib_decode_response(s, operation);
1146 break;
1147
1148 case SCARD_IOCTL_SETATTRIB:
1149 status = smartcard_SetAttrib_decode_response(s, operation);
1150 break;
1151
1152 default:
1153 WLog_WARN(TAG, "unsupported response for %s (0x%08" PRIX32 ")",
1154 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
1155 break;
1156 }
1157
1158 if (status != SCARD_S_SUCCESS)
1159 return status;
1160
1161 const size_t offset = startPosition + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH;
1162 if (smartcard_unpack_read_size_align(s, Stream_GetPosition(s) - offset, 8) < 0)
1163 return STATUS_INVALID_PARAMETER;
1164
1165 return status;
1166}
1167
1168static LONG smartcard_EstablishContext_encode_request(wStream* s,
1169 const SMARTCARD_OPERATION* operation)
1170{
1171 WINPR_ASSERT(s);
1172 WINPR_ASSERT(operation);
1173
1174 return smartcard_pack_establish_context_call(s, &operation->call.establishContext);
1175}
1176
1177static LONG smartcard_ReleaseContext_encode_request(wStream* s,
1178 const SMARTCARD_OPERATION* operation)
1179{
1180 WINPR_ASSERT(s);
1181 WINPR_ASSERT(operation);
1182
1183 return smartcard_pack_context_call(s, &operation->call.context, "ReleaseContext");
1184}
1185
1186static LONG smartcard_IsValidContext_encode_request(wStream* s,
1187 const SMARTCARD_OPERATION* operation)
1188{
1189 WINPR_ASSERT(s);
1190 WINPR_ASSERT(operation);
1191
1192 return smartcard_pack_context_call(s, &operation->call.context, "IsValidContext");
1193}
1194
1195static LONG smartcard_ListReaderGroupsA_encode_request(wStream* s,
1196 const SMARTCARD_OPERATION* operation)
1197{
1198 WINPR_ASSERT(s);
1199 WINPR_ASSERT(operation);
1200
1201 return smartcard_pack_list_reader_groups_call(s, &operation->call.listReaderGroups, FALSE);
1202}
1203
1204static LONG smartcard_ListReaderGroupsW_encode_request(wStream* s,
1205 const SMARTCARD_OPERATION* operation)
1206{
1207 WINPR_ASSERT(s);
1208 WINPR_ASSERT(operation);
1209
1210 return smartcard_pack_list_reader_groups_call(s, &operation->call.listReaderGroups, TRUE);
1211}
1212
1213static LONG smartcard_ListReadersA_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1214{
1215 WINPR_ASSERT(s);
1216 WINPR_ASSERT(operation);
1217
1218 return smartcard_pack_list_readers_call(s, &operation->call.listReaders, FALSE);
1219}
1220
1221static LONG smartcard_ListReadersW_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1222{
1223 WINPR_ASSERT(s);
1224 WINPR_ASSERT(operation);
1225
1226 return smartcard_pack_list_readers_call(s, &operation->call.listReaders, TRUE);
1227}
1228
1229static LONG smartcard_GetStatusChangeA_encode_request(wStream* s,
1230 const SMARTCARD_OPERATION* operation)
1231{
1232 WINPR_ASSERT(s);
1233 WINPR_ASSERT(operation);
1234
1235 return smartcard_pack_get_status_change_a_call(s, &operation->call.getStatusChangeA);
1236}
1237
1238static LONG smartcard_GetStatusChangeW_encode_request(wStream* s,
1239 const SMARTCARD_OPERATION* operation)
1240{
1241 WINPR_ASSERT(s);
1242 WINPR_ASSERT(operation);
1243
1244 return smartcard_pack_get_status_change_w_call(s, &operation->call.getStatusChangeW);
1245}
1246
1247static LONG smartcard_Cancel_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1248{
1249 WINPR_ASSERT(s);
1250 WINPR_ASSERT(operation);
1251
1252 return smartcard_pack_context_call(s, &operation->call.context, "Cancel");
1253}
1254
1255static LONG smartcard_ConnectA_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1256{
1257 WINPR_ASSERT(s);
1258 WINPR_ASSERT(operation);
1259
1260 return smartcard_pack_connect_a_call(s, &operation->call.connectA);
1261}
1262
1263static LONG smartcard_ConnectW_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1264{
1265 WINPR_ASSERT(s);
1266 WINPR_ASSERT(operation);
1267
1268 return smartcard_pack_connect_w_call(s, &operation->call.connectW);
1269}
1270
1271static LONG smartcard_Reconnect_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1272{
1273 WINPR_ASSERT(s);
1274 WINPR_ASSERT(operation);
1275
1276 return smartcard_pack_reconnect_call(s, &operation->call.reconnect);
1277}
1278
1279static LONG smartcard_Disconnect_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1280{
1281 WINPR_ASSERT(s);
1282 WINPR_ASSERT(operation);
1283
1284 return smartcard_pack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
1285 "Disconnect");
1286}
1287
1288static LONG smartcard_BeginTransaction_encode_request(wStream* s,
1289 const SMARTCARD_OPERATION* operation)
1290{
1291 WINPR_ASSERT(s);
1292 WINPR_ASSERT(operation);
1293
1294 return smartcard_pack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
1295 "BeginTransaction");
1296}
1297
1298static LONG smartcard_EndTransaction_encode_request(wStream* s,
1299 const SMARTCARD_OPERATION* operation)
1300{
1301 WINPR_ASSERT(s);
1302 WINPR_ASSERT(operation);
1303
1304 return smartcard_pack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
1305 "EndTransaction");
1306}
1307
1308static LONG smartcard_StatusA_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1309{
1310 WINPR_ASSERT(s);
1311 WINPR_ASSERT(operation);
1312
1313 return smartcard_pack_status_call(s, &operation->call.status, FALSE);
1314}
1315
1316static LONG smartcard_StatusW_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1317{
1318 WINPR_ASSERT(s);
1319 WINPR_ASSERT(operation);
1320
1321 return smartcard_pack_status_call(s, &operation->call.status, TRUE);
1322}
1323
1324static LONG smartcard_Transmit_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1325{
1326 WINPR_ASSERT(s);
1327 WINPR_ASSERT(operation);
1328
1329 return smartcard_pack_transmit_call(s, &operation->call.transmit);
1330}
1331
1332static LONG smartcard_Control_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1333{
1334 WINPR_ASSERT(s);
1335 WINPR_ASSERT(operation);
1336
1337 return smartcard_pack_control_call(s, &operation->call.control);
1338}
1339
1340static LONG smartcard_GetAttrib_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1341{
1342 WINPR_ASSERT(s);
1343 WINPR_ASSERT(operation);
1344
1345 return smartcard_pack_get_attrib_call(s, &operation->call.getAttrib);
1346}
1347
1348static LONG smartcard_SetAttrib_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1349{
1350 WINPR_ASSERT(s);
1351 WINPR_ASSERT(operation);
1352
1353 return smartcard_pack_set_attrib_call(s, &operation->call.setAttrib);
1354}
1355
1356LONG smartcard_irp_device_control_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1357{
1358 LONG status = SCARD_S_SUCCESS;
1359
1360 WINPR_ASSERT(s);
1361 WINPR_ASSERT(operation);
1362
1363 const UINT32 ioControlCode = operation->ioControlCode;
1364
1365 const size_t headerPos = Stream_GetPosition(s);
1366 Stream_Zero(s, SMARTCARD_COMMON_TYPE_HEADER_LENGTH); /* CommonTypeHeader (8 bytes) */
1367 Stream_Zero(s, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH); /* PrivateTypeHeader (8 bytes) */
1368
1369 switch (ioControlCode)
1370 {
1371 case SCARD_IOCTL_ESTABLISHCONTEXT:
1372 status = smartcard_EstablishContext_encode_request(s, operation);
1373 break;
1374
1375 case SCARD_IOCTL_RELEASECONTEXT:
1376 status = smartcard_ReleaseContext_encode_request(s, operation);
1377 break;
1378
1379 case SCARD_IOCTL_ISVALIDCONTEXT:
1380 status = smartcard_IsValidContext_encode_request(s, operation);
1381 break;
1382
1383 case SCARD_IOCTL_LISTREADERGROUPSA:
1384 status = smartcard_ListReaderGroupsA_encode_request(s, operation);
1385 break;
1386
1387 case SCARD_IOCTL_LISTREADERGROUPSW:
1388 status = smartcard_ListReaderGroupsW_encode_request(s, operation);
1389 break;
1390
1391 case SCARD_IOCTL_LISTREADERSA:
1392 status = smartcard_ListReadersA_encode_request(s, operation);
1393 break;
1394
1395 case SCARD_IOCTL_LISTREADERSW:
1396 status = smartcard_ListReadersW_encode_request(s, operation);
1397 break;
1398
1399 case SCARD_IOCTL_GETSTATUSCHANGEA:
1400 status = smartcard_GetStatusChangeA_encode_request(s, operation);
1401 break;
1402
1403 case SCARD_IOCTL_GETSTATUSCHANGEW:
1404 status = smartcard_GetStatusChangeW_encode_request(s, operation);
1405 break;
1406
1407 case SCARD_IOCTL_CANCEL:
1408 status = smartcard_Cancel_encode_request(s, operation);
1409 break;
1410
1411 case SCARD_IOCTL_CONNECTA:
1412 status = smartcard_ConnectA_encode_request(s, operation);
1413 break;
1414
1415 case SCARD_IOCTL_CONNECTW:
1416 status = smartcard_ConnectW_encode_request(s, operation);
1417 break;
1418
1419 case SCARD_IOCTL_RECONNECT:
1420 status = smartcard_Reconnect_encode_request(s, operation);
1421 break;
1422
1423 case SCARD_IOCTL_DISCONNECT:
1424 status = smartcard_Disconnect_encode_request(s, operation);
1425 break;
1426
1427 case SCARD_IOCTL_BEGINTRANSACTION:
1428 status = smartcard_BeginTransaction_encode_request(s, operation);
1429 break;
1430
1431 case SCARD_IOCTL_ENDTRANSACTION:
1432 status = smartcard_EndTransaction_encode_request(s, operation);
1433 break;
1434
1435 case SCARD_IOCTL_STATUSA:
1436 status = smartcard_StatusA_encode_request(s, operation);
1437 break;
1438
1439 case SCARD_IOCTL_STATUSW:
1440 status = smartcard_StatusW_encode_request(s, operation);
1441 break;
1442
1443 case SCARD_IOCTL_TRANSMIT:
1444 status = smartcard_Transmit_encode_request(s, operation);
1445 break;
1446
1447 case SCARD_IOCTL_CONTROL:
1448 status = smartcard_Control_encode_request(s, operation);
1449 break;
1450
1451 case SCARD_IOCTL_GETATTRIB:
1452 status = smartcard_GetAttrib_encode_request(s, operation);
1453 break;
1454
1455 case SCARD_IOCTL_SETATTRIB:
1456 status = smartcard_SetAttrib_encode_request(s, operation);
1457 break;
1458
1459 default:
1460 WLog_WARN(TAG, "unsupported request for %s (0x%08" PRIX32 ")",
1461 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
1462 return SCARD_E_UNSUPPORTED_FEATURE;
1463 }
1464
1465 if (status != SCARD_S_SUCCESS)
1466 return status;
1467
1468 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
1469 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
1470 {
1471 const LONG rc = smartcard_pack_write_size_align(s, Stream_GetPosition(s), 8);
1472 if (rc != SCARD_S_SUCCESS)
1473 return rc;
1474 }
1475
1476 const size_t dataEndPos = Stream_GetPosition(s);
1477 const size_t payloadSize = dataEndPos - headerPos;
1478 const size_t objectBufferLength =
1479 payloadSize - SMARTCARD_COMMON_TYPE_HEADER_LENGTH - SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH;
1480
1481 status = smartcard_pack_write_size_align(s, payloadSize, 8);
1482 if (status != SCARD_S_SUCCESS)
1483 return status;
1484
1485 const size_t endPos = Stream_GetPosition(s);
1486 if (!Stream_SetPosition(s, headerPos))
1487 return SCARD_E_BAD_SEEK;
1488 smartcard_pack_common_type_header(s);
1489 smartcard_pack_private_type_header(s, (UINT32)objectBufferLength);
1490 if (!Stream_SetPosition(s, endPos))
1491 return SCARD_E_BAD_SEEK;
1492 Stream_SealLength(s);
1493
1494 return status;
1495}
1496
1497static void free_reader_states_a(LPSCARD_READERSTATEA rgReaderStates, UINT32 cReaders)
1498{
1499 for (UINT32 x = 0; x < cReaders; x++)
1500 {
1501 SCARD_READERSTATEA* state = &rgReaderStates[x];
1502 free(state->szReader);
1503 }
1504
1505 free(rgReaderStates);
1506}
1507
1508static void free_reader_states_w(LPSCARD_READERSTATEW rgReaderStates, UINT32 cReaders)
1509{
1510 for (UINT32 x = 0; x < cReaders; x++)
1511 {
1512 SCARD_READERSTATEW* state = &rgReaderStates[x];
1513 free(state->szReader);
1514 }
1515
1516 free(rgReaderStates);
1517}
1518
1519void smartcard_operation_free(SMARTCARD_OPERATION* op, BOOL allocated)
1520{
1521 if (!op)
1522 return;
1523
1524 /* Free resources in the call union */
1525 switch (op->ioControlCode)
1526 {
1527 case SCARD_IOCTL_CANCEL:
1528 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
1529 case SCARD_IOCTL_RELEASETARTEDEVENT:
1530 case SCARD_IOCTL_LISTREADERGROUPSA:
1531 case SCARD_IOCTL_LISTREADERGROUPSW:
1532 case SCARD_IOCTL_RECONNECT:
1533 case SCARD_IOCTL_DISCONNECT:
1534 case SCARD_IOCTL_BEGINTRANSACTION:
1535 case SCARD_IOCTL_ENDTRANSACTION:
1536 case SCARD_IOCTL_STATE:
1537 case SCARD_IOCTL_STATUSA:
1538 case SCARD_IOCTL_STATUSW:
1539 case SCARD_IOCTL_ESTABLISHCONTEXT:
1540 case SCARD_IOCTL_RELEASECONTEXT:
1541 case SCARD_IOCTL_ISVALIDCONTEXT:
1542 case SCARD_IOCTL_GETATTRIB:
1543 case SCARD_IOCTL_GETTRANSMITCOUNT:
1544 break;
1545 case SCARD_IOCTL_LOCATECARDSA:
1546 {
1547 LocateCardsA_Call* call = &op->call.locateCardsA;
1548 free(call->mszCards);
1549
1550 free_reader_states_a(call->rgReaderStates, call->cReaders);
1551 }
1552 break;
1553 case SCARD_IOCTL_LOCATECARDSW:
1554 {
1555 LocateCardsW_Call* call = &op->call.locateCardsW;
1556 free(call->mszCards);
1557
1558 free_reader_states_w(call->rgReaderStates, call->cReaders);
1559 }
1560 break;
1561 case SCARD_IOCTL_LOCATECARDSBYATRA:
1562 {
1563 LocateCardsByATRA_Call* call = &op->call.locateCardsByATRA;
1564
1565 free_reader_states_a(call->rgReaderStates, call->cReaders);
1566 }
1567 break;
1568 case SCARD_IOCTL_LOCATECARDSBYATRW:
1569 {
1570 LocateCardsByATRW_Call* call = &op->call.locateCardsByATRW;
1571 free_reader_states_w(call->rgReaderStates, call->cReaders);
1572 }
1573 break;
1574 case SCARD_IOCTL_FORGETREADERA:
1575 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1576 case SCARD_IOCTL_FORGETREADERGROUPA:
1577 {
1578 ContextAndStringA_Call* call = &op->call.contextAndStringA;
1579 free(call->sz);
1580 }
1581 break;
1582 case SCARD_IOCTL_FORGETREADERW:
1583 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1584 case SCARD_IOCTL_FORGETREADERGROUPW:
1585 {
1586 ContextAndStringW_Call* call = &op->call.contextAndStringW;
1587 free(call->sz);
1588 }
1589 break;
1590 case SCARD_IOCTL_INTRODUCEREADERA:
1591 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1592 case SCARD_IOCTL_ADDREADERTOGROUPA:
1593 {
1594 ContextAndTwoStringA_Call* call = &op->call.contextAndTwoStringA;
1595 free(call->sz1);
1596 free(call->sz2);
1597 }
1598 break;
1599 case SCARD_IOCTL_INTRODUCEREADERW:
1600 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1601 case SCARD_IOCTL_ADDREADERTOGROUPW:
1602 {
1603 ContextAndTwoStringW_Call* call = &op->call.contextAndTwoStringW;
1604 free(call->sz1);
1605 free(call->sz2);
1606 }
1607 break;
1608 case SCARD_IOCTL_LISTREADERSA:
1609 case SCARD_IOCTL_LISTREADERSW:
1610 {
1611 ListReaders_Call* call = &op->call.listReaders;
1612 free(call->mszGroups);
1613 }
1614 break;
1615 case SCARD_IOCTL_GETSTATUSCHANGEA:
1616 {
1617 GetStatusChangeA_Call* call = &op->call.getStatusChangeA;
1618 free_reader_states_a(call->rgReaderStates, call->cReaders);
1619 }
1620 break;
1621 case SCARD_IOCTL_GETSTATUSCHANGEW:
1622 {
1623 GetStatusChangeW_Call* call = &op->call.getStatusChangeW;
1624 free_reader_states_w(call->rgReaderStates, call->cReaders);
1625 }
1626 break;
1627 case SCARD_IOCTL_GETREADERICON:
1628 {
1629 GetReaderIcon_Call* call = &op->call.getReaderIcon;
1630 free(call->szReaderName);
1631 }
1632 break;
1633 case SCARD_IOCTL_GETDEVICETYPEID:
1634 {
1635 GetDeviceTypeId_Call* call = &op->call.getDeviceTypeId;
1636 free(call->szReaderName);
1637 }
1638 break;
1639 case SCARD_IOCTL_CONNECTA:
1640 {
1641 ConnectA_Call* call = &op->call.connectA;
1642 free(call->szReader);
1643 }
1644 break;
1645 case SCARD_IOCTL_CONNECTW:
1646 {
1647 ConnectW_Call* call = &op->call.connectW;
1648 free(call->szReader);
1649 }
1650 break;
1651 case SCARD_IOCTL_SETATTRIB:
1652 free(op->call.setAttrib.pbAttr);
1653 break;
1654 case SCARD_IOCTL_TRANSMIT:
1655 {
1656 Transmit_Call* call = &op->call.transmit;
1657 free(call->pbSendBuffer);
1658 free(call->pioSendPci);
1659 free(call->pioRecvPci);
1660 }
1661 break;
1662 case SCARD_IOCTL_CONTROL:
1663 {
1664 Control_Call* call = &op->call.control;
1665 free(call->pvInBuffer);
1666 }
1667 break;
1668 case SCARD_IOCTL_READCACHEA:
1669 {
1670 ReadCacheA_Call* call = &op->call.readCacheA;
1671 free(call->szLookupName);
1672 free(call->Common.CardIdentifier);
1673 }
1674 break;
1675 case SCARD_IOCTL_READCACHEW:
1676 {
1677 ReadCacheW_Call* call = &op->call.readCacheW;
1678 free(call->szLookupName);
1679 free(call->Common.CardIdentifier);
1680 }
1681 break;
1682 case SCARD_IOCTL_WRITECACHEA:
1683 {
1684 WriteCacheA_Call* call = &op->call.writeCacheA;
1685 free(call->szLookupName);
1686 free(call->Common.CardIdentifier);
1687 free(call->Common.pbData);
1688 }
1689 break;
1690 case SCARD_IOCTL_WRITECACHEW:
1691 {
1692 WriteCacheW_Call* call = &op->call.writeCacheW;
1693 free(call->szLookupName);
1694 free(call->Common.CardIdentifier);
1695 free(call->Common.pbData);
1696 }
1697 break;
1698 default:
1699 break;
1700 }
1701
1702 /* Free resources in the ret union */
1703 switch (op->ioControlCode)
1704 {
1705 case SCARD_IOCTL_LISTREADERSA:
1706 case SCARD_IOCTL_LISTREADERSW:
1707 case SCARD_IOCTL_LISTREADERGROUPSA:
1708 case SCARD_IOCTL_LISTREADERGROUPSW:
1709 {
1710 ListReaders_Return* ret = &op->ret.listReaders;
1711 free(ret->msz);
1712 }
1713 break;
1714 case SCARD_IOCTL_STATUSA:
1715 case SCARD_IOCTL_STATUSW:
1716 {
1717 Status_Return* ret = &op->ret.status;
1718 free(ret->mszReaderNames);
1719 }
1720 break;
1721 case SCARD_IOCTL_GETSTATUSCHANGEA:
1722 case SCARD_IOCTL_GETSTATUSCHANGEW:
1723 {
1724 GetStatusChange_Return* ret = &op->ret.getStatusChange;
1725 free(ret->rgReaderStates);
1726 }
1727 break;
1728 case SCARD_IOCTL_TRANSMIT:
1729 {
1730 Transmit_Return* ret = &op->ret.transmit;
1731 free(ret->pbRecvBuffer);
1732 free(ret->pioRecvPci);
1733 }
1734 break;
1735 case SCARD_IOCTL_CONTROL:
1736 {
1737 Control_Return* call = &op->ret.control;
1738 free(call->pvOutBuffer);
1739 }
1740 break;
1741 case SCARD_IOCTL_GETATTRIB:
1742 {
1743 GetAttrib_Return* ret = &op->ret.getAttrib;
1744 free(ret->pbAttr);
1745 }
1746 break;
1747 default:
1748 break;
1749 }
1750
1751 {
1752 SMARTCARD_OPERATION empty = WINPR_C_ARRAY_INIT;
1753 *op = empty;
1754 }
1755
1756 if (allocated)
1757 free(op);
1758}
union SMARTCARD_OPERATION::@30 ret