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_WARN(TAG, "%s failed with ReturnCode %s [0x%08" PRIX32 "]",
1058 scard_get_ioctl_string(ioControlCode, TRUE),
1059 SCardGetErrorString(operation->returnCode), (UINT32)operation->returnCode);
1060 return SCARD_S_SUCCESS;
1061 }
1062
1063 switch (ioControlCode)
1064 {
1065 case SCARD_IOCTL_ESTABLISHCONTEXT:
1066 status = smartcard_EstablishContext_decode_response(s, operation);
1067 break;
1068
1069 case SCARD_IOCTL_RELEASECONTEXT:
1070 status = smartcard_ReleaseContext_decode_response(s, operation);
1071 break;
1072
1073 case SCARD_IOCTL_ISVALIDCONTEXT:
1074 status = smartcard_IsValidContext_decode_response(s, operation);
1075 break;
1076
1077 case SCARD_IOCTL_LISTREADERGROUPSA:
1078 status = smartcard_ListReaderGroupsA_decode_response(s, operation);
1079 break;
1080
1081 case SCARD_IOCTL_LISTREADERGROUPSW:
1082 status = smartcard_ListReaderGroupsW_decode_response(s, operation);
1083 break;
1084
1085 case SCARD_IOCTL_LISTREADERSA:
1086 status = smartcard_ListReadersA_decode_response(s, operation);
1087 break;
1088
1089 case SCARD_IOCTL_LISTREADERSW:
1090 status = smartcard_ListReadersW_decode_response(s, operation);
1091 break;
1092
1093 case SCARD_IOCTL_GETSTATUSCHANGEA:
1094 status = smartcard_GetStatusChangeA_decode_response(s, operation);
1095 break;
1096
1097 case SCARD_IOCTL_GETSTATUSCHANGEW:
1098 status = smartcard_GetStatusChangeW_decode_response(s, operation);
1099 break;
1100
1101 case SCARD_IOCTL_CANCEL:
1102 status = smartcard_Cancel_decode_response(s, operation);
1103 break;
1104
1105 case SCARD_IOCTL_CONNECTA:
1106 status = smartcard_ConnectA_decode_response(s, operation);
1107 break;
1108
1109 case SCARD_IOCTL_CONNECTW:
1110 status = smartcard_ConnectW_decode_response(s, operation);
1111 break;
1112
1113 case SCARD_IOCTL_RECONNECT:
1114 status = smartcard_Reconnect_decode_response(s, operation);
1115 break;
1116
1117 case SCARD_IOCTL_DISCONNECT:
1118 status = smartcard_Disconnect_decode_response(s, operation);
1119 break;
1120
1121 case SCARD_IOCTL_BEGINTRANSACTION:
1122 status = smartcard_BeginTransaction_decode_response(s, operation);
1123 break;
1124
1125 case SCARD_IOCTL_ENDTRANSACTION:
1126 status = smartcard_EndTransaction_decode_response(s, operation);
1127 break;
1128
1129 case SCARD_IOCTL_STATUSA:
1130 status = smartcard_StatusA_decode_response(s, operation);
1131 break;
1132
1133 case SCARD_IOCTL_STATUSW:
1134 status = smartcard_StatusW_decode_response(s, operation);
1135 break;
1136
1137 case SCARD_IOCTL_TRANSMIT:
1138 status = smartcard_Transmit_decode_response(s, operation);
1139 break;
1140
1141 case SCARD_IOCTL_CONTROL:
1142 status = smartcard_Control_decode_response(s, operation);
1143 break;
1144
1145 case SCARD_IOCTL_GETATTRIB:
1146 status = smartcard_GetAttrib_decode_response(s, operation);
1147 break;
1148
1149 case SCARD_IOCTL_SETATTRIB:
1150 status = smartcard_SetAttrib_decode_response(s, operation);
1151 break;
1152
1153 default:
1154 WLog_WARN(TAG, "unsupported response for %s (0x%08" PRIX32 ")",
1155 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
1156 break;
1157 }
1158
1159 if (status != SCARD_S_SUCCESS)
1160 return status;
1161
1162 const size_t offset = startPosition + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH;
1163 if (smartcard_unpack_read_size_align(s, Stream_GetPosition(s) - offset, 8) < 0)
1164 return STATUS_INVALID_PARAMETER;
1165
1166 return status;
1167}
1168
1169static LONG smartcard_EstablishContext_encode_request(wStream* s,
1170 const SMARTCARD_OPERATION* operation)
1171{
1172 WINPR_ASSERT(s);
1173 WINPR_ASSERT(operation);
1174
1175 return smartcard_pack_establish_context_call(s, &operation->call.establishContext);
1176}
1177
1178static LONG smartcard_ReleaseContext_encode_request(wStream* s,
1179 const SMARTCARD_OPERATION* operation)
1180{
1181 WINPR_ASSERT(s);
1182 WINPR_ASSERT(operation);
1183
1184 return smartcard_pack_context_call(s, &operation->call.context, "ReleaseContext");
1185}
1186
1187static LONG smartcard_IsValidContext_encode_request(wStream* s,
1188 const SMARTCARD_OPERATION* operation)
1189{
1190 WINPR_ASSERT(s);
1191 WINPR_ASSERT(operation);
1192
1193 return smartcard_pack_context_call(s, &operation->call.context, "IsValidContext");
1194}
1195
1196static LONG smartcard_ListReaderGroupsA_encode_request(wStream* s,
1197 const SMARTCARD_OPERATION* operation)
1198{
1199 WINPR_ASSERT(s);
1200 WINPR_ASSERT(operation);
1201
1202 return smartcard_pack_list_reader_groups_call(s, &operation->call.listReaderGroups, FALSE);
1203}
1204
1205static LONG smartcard_ListReaderGroupsW_encode_request(wStream* s,
1206 const SMARTCARD_OPERATION* operation)
1207{
1208 WINPR_ASSERT(s);
1209 WINPR_ASSERT(operation);
1210
1211 return smartcard_pack_list_reader_groups_call(s, &operation->call.listReaderGroups, TRUE);
1212}
1213
1214static LONG smartcard_ListReadersA_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1215{
1216 WINPR_ASSERT(s);
1217 WINPR_ASSERT(operation);
1218
1219 return smartcard_pack_list_readers_call(s, &operation->call.listReaders, FALSE);
1220}
1221
1222static LONG smartcard_ListReadersW_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1223{
1224 WINPR_ASSERT(s);
1225 WINPR_ASSERT(operation);
1226
1227 return smartcard_pack_list_readers_call(s, &operation->call.listReaders, TRUE);
1228}
1229
1230static LONG smartcard_GetStatusChangeA_encode_request(wStream* s,
1231 const SMARTCARD_OPERATION* operation)
1232{
1233 WINPR_ASSERT(s);
1234 WINPR_ASSERT(operation);
1235
1236 return smartcard_pack_get_status_change_a_call(s, &operation->call.getStatusChangeA);
1237}
1238
1239static LONG smartcard_GetStatusChangeW_encode_request(wStream* s,
1240 const SMARTCARD_OPERATION* operation)
1241{
1242 WINPR_ASSERT(s);
1243 WINPR_ASSERT(operation);
1244
1245 return smartcard_pack_get_status_change_w_call(s, &operation->call.getStatusChangeW);
1246}
1247
1248static LONG smartcard_Cancel_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1249{
1250 WINPR_ASSERT(s);
1251 WINPR_ASSERT(operation);
1252
1253 return smartcard_pack_context_call(s, &operation->call.context, "Cancel");
1254}
1255
1256static LONG smartcard_ConnectA_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1257{
1258 WINPR_ASSERT(s);
1259 WINPR_ASSERT(operation);
1260
1261 return smartcard_pack_connect_a_call(s, &operation->call.connectA);
1262}
1263
1264static LONG smartcard_ConnectW_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1265{
1266 WINPR_ASSERT(s);
1267 WINPR_ASSERT(operation);
1268
1269 return smartcard_pack_connect_w_call(s, &operation->call.connectW);
1270}
1271
1272static LONG smartcard_Reconnect_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1273{
1274 WINPR_ASSERT(s);
1275 WINPR_ASSERT(operation);
1276
1277 return smartcard_pack_reconnect_call(s, &operation->call.reconnect);
1278}
1279
1280static LONG smartcard_Disconnect_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1281{
1282 WINPR_ASSERT(s);
1283 WINPR_ASSERT(operation);
1284
1285 return smartcard_pack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
1286 "Disconnect");
1287}
1288
1289static LONG smartcard_BeginTransaction_encode_request(wStream* s,
1290 const SMARTCARD_OPERATION* operation)
1291{
1292 WINPR_ASSERT(s);
1293 WINPR_ASSERT(operation);
1294
1295 return smartcard_pack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
1296 "BeginTransaction");
1297}
1298
1299static LONG smartcard_EndTransaction_encode_request(wStream* s,
1300 const SMARTCARD_OPERATION* operation)
1301{
1302 WINPR_ASSERT(s);
1303 WINPR_ASSERT(operation);
1304
1305 return smartcard_pack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
1306 "EndTransaction");
1307}
1308
1309static LONG smartcard_StatusA_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1310{
1311 WINPR_ASSERT(s);
1312 WINPR_ASSERT(operation);
1313
1314 return smartcard_pack_status_call(s, &operation->call.status, FALSE);
1315}
1316
1317static LONG smartcard_StatusW_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1318{
1319 WINPR_ASSERT(s);
1320 WINPR_ASSERT(operation);
1321
1322 return smartcard_pack_status_call(s, &operation->call.status, TRUE);
1323}
1324
1325static LONG smartcard_Transmit_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1326{
1327 WINPR_ASSERT(s);
1328 WINPR_ASSERT(operation);
1329
1330 return smartcard_pack_transmit_call(s, &operation->call.transmit);
1331}
1332
1333static LONG smartcard_Control_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1334{
1335 WINPR_ASSERT(s);
1336 WINPR_ASSERT(operation);
1337
1338 return smartcard_pack_control_call(s, &operation->call.control);
1339}
1340
1341static LONG smartcard_GetAttrib_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1342{
1343 WINPR_ASSERT(s);
1344 WINPR_ASSERT(operation);
1345
1346 return smartcard_pack_get_attrib_call(s, &operation->call.getAttrib);
1347}
1348
1349static LONG smartcard_SetAttrib_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1350{
1351 WINPR_ASSERT(s);
1352 WINPR_ASSERT(operation);
1353
1354 return smartcard_pack_set_attrib_call(s, &operation->call.setAttrib);
1355}
1356
1357LONG smartcard_irp_device_control_encode_request(wStream* s, const SMARTCARD_OPERATION* operation)
1358{
1359 LONG status = SCARD_S_SUCCESS;
1360
1361 WINPR_ASSERT(s);
1362 WINPR_ASSERT(operation);
1363
1364 const UINT32 ioControlCode = operation->ioControlCode;
1365
1366 const size_t headerPos = Stream_GetPosition(s);
1367 Stream_Zero(s, SMARTCARD_COMMON_TYPE_HEADER_LENGTH); /* CommonTypeHeader (8 bytes) */
1368 Stream_Zero(s, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH); /* PrivateTypeHeader (8 bytes) */
1369
1370 switch (ioControlCode)
1371 {
1372 case SCARD_IOCTL_ESTABLISHCONTEXT:
1373 status = smartcard_EstablishContext_encode_request(s, operation);
1374 break;
1375
1376 case SCARD_IOCTL_RELEASECONTEXT:
1377 status = smartcard_ReleaseContext_encode_request(s, operation);
1378 break;
1379
1380 case SCARD_IOCTL_ISVALIDCONTEXT:
1381 status = smartcard_IsValidContext_encode_request(s, operation);
1382 break;
1383
1384 case SCARD_IOCTL_LISTREADERGROUPSA:
1385 status = smartcard_ListReaderGroupsA_encode_request(s, operation);
1386 break;
1387
1388 case SCARD_IOCTL_LISTREADERGROUPSW:
1389 status = smartcard_ListReaderGroupsW_encode_request(s, operation);
1390 break;
1391
1392 case SCARD_IOCTL_LISTREADERSA:
1393 status = smartcard_ListReadersA_encode_request(s, operation);
1394 break;
1395
1396 case SCARD_IOCTL_LISTREADERSW:
1397 status = smartcard_ListReadersW_encode_request(s, operation);
1398 break;
1399
1400 case SCARD_IOCTL_GETSTATUSCHANGEA:
1401 status = smartcard_GetStatusChangeA_encode_request(s, operation);
1402 break;
1403
1404 case SCARD_IOCTL_GETSTATUSCHANGEW:
1405 status = smartcard_GetStatusChangeW_encode_request(s, operation);
1406 break;
1407
1408 case SCARD_IOCTL_CANCEL:
1409 status = smartcard_Cancel_encode_request(s, operation);
1410 break;
1411
1412 case SCARD_IOCTL_CONNECTA:
1413 status = smartcard_ConnectA_encode_request(s, operation);
1414 break;
1415
1416 case SCARD_IOCTL_CONNECTW:
1417 status = smartcard_ConnectW_encode_request(s, operation);
1418 break;
1419
1420 case SCARD_IOCTL_RECONNECT:
1421 status = smartcard_Reconnect_encode_request(s, operation);
1422 break;
1423
1424 case SCARD_IOCTL_DISCONNECT:
1425 status = smartcard_Disconnect_encode_request(s, operation);
1426 break;
1427
1428 case SCARD_IOCTL_BEGINTRANSACTION:
1429 status = smartcard_BeginTransaction_encode_request(s, operation);
1430 break;
1431
1432 case SCARD_IOCTL_ENDTRANSACTION:
1433 status = smartcard_EndTransaction_encode_request(s, operation);
1434 break;
1435
1436 case SCARD_IOCTL_STATUSA:
1437 status = smartcard_StatusA_encode_request(s, operation);
1438 break;
1439
1440 case SCARD_IOCTL_STATUSW:
1441 status = smartcard_StatusW_encode_request(s, operation);
1442 break;
1443
1444 case SCARD_IOCTL_TRANSMIT:
1445 status = smartcard_Transmit_encode_request(s, operation);
1446 break;
1447
1448 case SCARD_IOCTL_CONTROL:
1449 status = smartcard_Control_encode_request(s, operation);
1450 break;
1451
1452 case SCARD_IOCTL_GETATTRIB:
1453 status = smartcard_GetAttrib_encode_request(s, operation);
1454 break;
1455
1456 case SCARD_IOCTL_SETATTRIB:
1457 status = smartcard_SetAttrib_encode_request(s, operation);
1458 break;
1459
1460 default:
1461 WLog_WARN(TAG, "unsupported request for %s (0x%08" PRIX32 ")",
1462 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
1463 return SCARD_E_UNSUPPORTED_FEATURE;
1464 }
1465
1466 if (status != SCARD_S_SUCCESS)
1467 return status;
1468
1469 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
1470 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
1471 {
1472 const LONG rc = smartcard_pack_write_size_align(s, Stream_GetPosition(s), 8);
1473 if (rc != SCARD_S_SUCCESS)
1474 return rc;
1475 }
1476
1477 const size_t dataEndPos = Stream_GetPosition(s);
1478 const size_t payloadSize = dataEndPos - headerPos;
1479 const size_t objectBufferLength =
1480 payloadSize - SMARTCARD_COMMON_TYPE_HEADER_LENGTH - SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH;
1481
1482 status = smartcard_pack_write_size_align(s, payloadSize, 8);
1483 if (status != SCARD_S_SUCCESS)
1484 return status;
1485
1486 const size_t endPos = Stream_GetPosition(s);
1487 if (!Stream_SetPosition(s, headerPos))
1488 return SCARD_E_BAD_SEEK;
1489 smartcard_pack_common_type_header(s);
1490 smartcard_pack_private_type_header(s, (UINT32)objectBufferLength);
1491 if (!Stream_SetPosition(s, endPos))
1492 return SCARD_E_BAD_SEEK;
1493 Stream_SealLength(s);
1494
1495 return status;
1496}
1497
1498static void free_reader_states_a(LPSCARD_READERSTATEA rgReaderStates, UINT32 cReaders)
1499{
1500 for (UINT32 x = 0; x < cReaders; x++)
1501 {
1502 SCARD_READERSTATEA* state = &rgReaderStates[x];
1503 free(state->szReader);
1504 }
1505
1506 free(rgReaderStates);
1507}
1508
1509static void free_reader_states_w(LPSCARD_READERSTATEW rgReaderStates, UINT32 cReaders)
1510{
1511 for (UINT32 x = 0; x < cReaders; x++)
1512 {
1513 SCARD_READERSTATEW* state = &rgReaderStates[x];
1514 free(state->szReader);
1515 }
1516
1517 free(rgReaderStates);
1518}
1519
1520void smartcard_operation_free(SMARTCARD_OPERATION* op, BOOL allocated)
1521{
1522 if (!op)
1523 return;
1524
1525 /* Free resources in the call union */
1526 switch (op->ioControlCode)
1527 {
1528 case SCARD_IOCTL_CANCEL:
1529 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
1530 case SCARD_IOCTL_RELEASETARTEDEVENT:
1531 case SCARD_IOCTL_LISTREADERGROUPSA:
1532 case SCARD_IOCTL_LISTREADERGROUPSW:
1533 case SCARD_IOCTL_RECONNECT:
1534 case SCARD_IOCTL_DISCONNECT:
1535 case SCARD_IOCTL_BEGINTRANSACTION:
1536 case SCARD_IOCTL_ENDTRANSACTION:
1537 case SCARD_IOCTL_STATE:
1538 case SCARD_IOCTL_STATUSA:
1539 case SCARD_IOCTL_STATUSW:
1540 case SCARD_IOCTL_ESTABLISHCONTEXT:
1541 case SCARD_IOCTL_RELEASECONTEXT:
1542 case SCARD_IOCTL_ISVALIDCONTEXT:
1543 case SCARD_IOCTL_GETATTRIB:
1544 case SCARD_IOCTL_GETTRANSMITCOUNT:
1545 break;
1546 case SCARD_IOCTL_LOCATECARDSA:
1547 {
1548 LocateCardsA_Call* call = &op->call.locateCardsA;
1549 free(call->mszCards);
1550
1551 free_reader_states_a(call->rgReaderStates, call->cReaders);
1552 }
1553 break;
1554 case SCARD_IOCTL_LOCATECARDSW:
1555 {
1556 LocateCardsW_Call* call = &op->call.locateCardsW;
1557 free(call->mszCards);
1558
1559 free_reader_states_w(call->rgReaderStates, call->cReaders);
1560 }
1561 break;
1562 case SCARD_IOCTL_LOCATECARDSBYATRA:
1563 {
1564 LocateCardsByATRA_Call* call = &op->call.locateCardsByATRA;
1565
1566 free_reader_states_a(call->rgReaderStates, call->cReaders);
1567 }
1568 break;
1569 case SCARD_IOCTL_LOCATECARDSBYATRW:
1570 {
1571 LocateCardsByATRW_Call* call = &op->call.locateCardsByATRW;
1572 free_reader_states_w(call->rgReaderStates, call->cReaders);
1573 }
1574 break;
1575 case SCARD_IOCTL_FORGETREADERA:
1576 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1577 case SCARD_IOCTL_FORGETREADERGROUPA:
1578 {
1579 ContextAndStringA_Call* call = &op->call.contextAndStringA;
1580 free(call->sz);
1581 }
1582 break;
1583 case SCARD_IOCTL_FORGETREADERW:
1584 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1585 case SCARD_IOCTL_FORGETREADERGROUPW:
1586 {
1587 ContextAndStringW_Call* call = &op->call.contextAndStringW;
1588 free(call->sz);
1589 }
1590 break;
1591 case SCARD_IOCTL_INTRODUCEREADERA:
1592 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1593 case SCARD_IOCTL_ADDREADERTOGROUPA:
1594 {
1595 ContextAndTwoStringA_Call* call = &op->call.contextAndTwoStringA;
1596 free(call->sz1);
1597 free(call->sz2);
1598 }
1599 break;
1600 case SCARD_IOCTL_INTRODUCEREADERW:
1601 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1602 case SCARD_IOCTL_ADDREADERTOGROUPW:
1603 {
1604 ContextAndTwoStringW_Call* call = &op->call.contextAndTwoStringW;
1605 free(call->sz1);
1606 free(call->sz2);
1607 }
1608 break;
1609 case SCARD_IOCTL_LISTREADERSA:
1610 case SCARD_IOCTL_LISTREADERSW:
1611 {
1612 ListReaders_Call* call = &op->call.listReaders;
1613 free(call->mszGroups);
1614 }
1615 break;
1616 case SCARD_IOCTL_GETSTATUSCHANGEA:
1617 {
1618 GetStatusChangeA_Call* call = &op->call.getStatusChangeA;
1619 free_reader_states_a(call->rgReaderStates, call->cReaders);
1620 }
1621 break;
1622 case SCARD_IOCTL_GETSTATUSCHANGEW:
1623 {
1624 GetStatusChangeW_Call* call = &op->call.getStatusChangeW;
1625 free_reader_states_w(call->rgReaderStates, call->cReaders);
1626 }
1627 break;
1628 case SCARD_IOCTL_GETREADERICON:
1629 {
1630 GetReaderIcon_Call* call = &op->call.getReaderIcon;
1631 free(call->szReaderName);
1632 }
1633 break;
1634 case SCARD_IOCTL_GETDEVICETYPEID:
1635 {
1636 GetDeviceTypeId_Call* call = &op->call.getDeviceTypeId;
1637 free(call->szReaderName);
1638 }
1639 break;
1640 case SCARD_IOCTL_CONNECTA:
1641 {
1642 ConnectA_Call* call = &op->call.connectA;
1643 free(call->szReader);
1644 }
1645 break;
1646 case SCARD_IOCTL_CONNECTW:
1647 {
1648 ConnectW_Call* call = &op->call.connectW;
1649 free(call->szReader);
1650 }
1651 break;
1652 case SCARD_IOCTL_SETATTRIB:
1653 free(op->call.setAttrib.pbAttr);
1654 break;
1655 case SCARD_IOCTL_TRANSMIT:
1656 {
1657 Transmit_Call* call = &op->call.transmit;
1658 free(call->pbSendBuffer);
1659 free(call->pioSendPci);
1660 free(call->pioRecvPci);
1661 }
1662 break;
1663 case SCARD_IOCTL_CONTROL:
1664 {
1665 Control_Call* call = &op->call.control;
1666 free(call->pvInBuffer);
1667 }
1668 break;
1669 case SCARD_IOCTL_READCACHEA:
1670 {
1671 ReadCacheA_Call* call = &op->call.readCacheA;
1672 free(call->szLookupName);
1673 free(call->Common.CardIdentifier);
1674 }
1675 break;
1676 case SCARD_IOCTL_READCACHEW:
1677 {
1678 ReadCacheW_Call* call = &op->call.readCacheW;
1679 free(call->szLookupName);
1680 free(call->Common.CardIdentifier);
1681 }
1682 break;
1683 case SCARD_IOCTL_WRITECACHEA:
1684 {
1685 WriteCacheA_Call* call = &op->call.writeCacheA;
1686 free(call->szLookupName);
1687 free(call->Common.CardIdentifier);
1688 free(call->Common.pbData);
1689 }
1690 break;
1691 case SCARD_IOCTL_WRITECACHEW:
1692 {
1693 WriteCacheW_Call* call = &op->call.writeCacheW;
1694 free(call->szLookupName);
1695 free(call->Common.CardIdentifier);
1696 free(call->Common.pbData);
1697 }
1698 break;
1699 default:
1700 break;
1701 }
1702
1703 /* Free resources in the ret union */
1704 switch (op->ioControlCode)
1705 {
1706 case SCARD_IOCTL_LISTREADERSA:
1707 case SCARD_IOCTL_LISTREADERSW:
1708 case SCARD_IOCTL_LISTREADERGROUPSA:
1709 case SCARD_IOCTL_LISTREADERGROUPSW:
1710 {
1711 ListReaders_Return* ret = &op->ret.listReaders;
1712 free(ret->msz);
1713 }
1714 break;
1715 case SCARD_IOCTL_STATUSA:
1716 case SCARD_IOCTL_STATUSW:
1717 {
1718 Status_Return* ret = &op->ret.status;
1719 free(ret->mszReaderNames);
1720 }
1721 break;
1722 case SCARD_IOCTL_GETSTATUSCHANGEA:
1723 case SCARD_IOCTL_GETSTATUSCHANGEW:
1724 {
1725 GetStatusChange_Return* ret = &op->ret.getStatusChange;
1726 free(ret->rgReaderStates);
1727 }
1728 break;
1729 case SCARD_IOCTL_TRANSMIT:
1730 {
1731 Transmit_Return* ret = &op->ret.transmit;
1732 free(ret->pbRecvBuffer);
1733 free(ret->pioRecvPci);
1734 }
1735 break;
1736 case SCARD_IOCTL_CONTROL:
1737 {
1738 Control_Return* call = &op->ret.control;
1739 free(call->pvOutBuffer);
1740 }
1741 break;
1742 case SCARD_IOCTL_GETATTRIB:
1743 {
1744 GetAttrib_Return* ret = &op->ret.getAttrib;
1745 free(ret->pbAttr);
1746 }
1747 break;
1748 default:
1749 break;
1750 }
1751
1752 {
1753 SMARTCARD_OPERATION empty = WINPR_C_ARRAY_INIT;
1754 *op = empty;
1755 }
1756
1757 if (allocated)
1758 free(op);
1759}
union SMARTCARD_OPERATION::@30 ret