26#include <freerdp/config.h>
28#include <winpr/assert.h>
31#include <winpr/print.h>
32#include <winpr/stream.h>
33#include <winpr/smartcard.h>
35#include <freerdp/freerdp.h>
36#include <freerdp/channels/rdpdr.h>
37#include <freerdp/channels/scard.h>
39#include <freerdp/utils/rdpdr_utils.h>
41#include <freerdp/utils/smartcard_operations.h>
42#include <freerdp/utils/smartcard_pack.h>
44#include <freerdp/log.h>
45#define TAG FREERDP_TAG("utils.smartcard.ops")
49 WINPR_ASSERT(operation);
52 smartcard_scard_context_native_from_redir(&(operation->call.handles.hContext));
53 operation->hCard = smartcard_scard_handle_native_from_redir(&(operation->call.handles.hCard));
55 return SCARD_S_SUCCESS;
63 WINPR_ASSERT(operation);
65 status = smartcard_unpack_establish_context_call(s, &operation->call.establishContext);
66 if (status != SCARD_S_SUCCESS)
68 return scard_log_status_error(TAG,
"smartcard_unpack_establish_context_call", status);
71 return SCARD_S_SUCCESS;
79 WINPR_ASSERT(operation);
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);
93 WINPR_ASSERT(operation);
95 status = smartcard_unpack_context_call(s, &operation->call.context,
"IsValidContext");
105 WINPR_ASSERT(operation);
107 status = smartcard_unpack_list_reader_groups_call(s, &operation->call.listReaderGroups, FALSE);
117 WINPR_ASSERT(operation);
119 status = smartcard_unpack_list_reader_groups_call(s, &operation->call.listReaderGroups, TRUE);
129 WINPR_ASSERT(operation);
131 status = smartcard_unpack_list_readers_call(s, &operation->call.listReaders, FALSE);
141 WINPR_ASSERT(operation);
143 status = smartcard_unpack_list_readers_call(s, &operation->call.listReaders, TRUE);
148static LONG smartcard_ContextAndTwoStringA_decode_request(
wStream* s,
154 WINPR_ASSERT(operation);
157 smartcard_unpack_context_and_two_strings_a_call(s, &operation->call.contextAndTwoStringA);
162static LONG smartcard_ContextAndTwoStringW_decode_request(
wStream* s,
168 WINPR_ASSERT(operation);
171 smartcard_unpack_context_and_two_strings_w_call(s, &operation->call.contextAndTwoStringW);
181 WINPR_ASSERT(operation);
183 status = smartcard_unpack_context_and_string_a_call(s, &operation->call.contextAndStringA);
193 WINPR_ASSERT(operation);
195 status = smartcard_unpack_context_and_string_w_call(s, &operation->call.contextAndStringW);
205 WINPR_ASSERT(operation);
207 status = smartcard_unpack_locate_cards_a_call(s, &operation->call.locateCardsA);
217 WINPR_ASSERT(operation);
219 status = smartcard_unpack_locate_cards_w_call(s, &operation->call.locateCardsW);
227 WINPR_ASSERT(operation);
229 return smartcard_unpack_get_status_change_a_call(s, &operation->call.getStatusChangeA);
235 WINPR_ASSERT(operation);
237 return smartcard_unpack_get_status_change_w_call(s, &operation->call.getStatusChangeW);
245 WINPR_ASSERT(operation);
247 status = smartcard_unpack_context_call(s, &operation->call.context,
"Cancel");
257 WINPR_ASSERT(operation);
259 status = smartcard_unpack_connect_a_call(s, &operation->call.connectA);
269 WINPR_ASSERT(operation);
271 status = smartcard_unpack_connect_w_call(s, &operation->call.connectW);
281 WINPR_ASSERT(operation);
283 status = smartcard_unpack_reconnect_call(s, &operation->call.reconnect);
293 WINPR_ASSERT(operation);
295 status = smartcard_unpack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
306 WINPR_ASSERT(operation);
308 status = smartcard_unpack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
319 WINPR_ASSERT(operation);
321 status = smartcard_unpack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
332 WINPR_ASSERT(operation);
334 status = smartcard_unpack_state_call(s, &operation->call.state);
344 WINPR_ASSERT(operation);
346 status = smartcard_unpack_status_call(s, &operation->call.status, FALSE);
356 WINPR_ASSERT(operation);
358 status = smartcard_unpack_status_call(s, &operation->call.status, TRUE);
368 WINPR_ASSERT(operation);
370 status = smartcard_unpack_transmit_call(s, &operation->call.transmit);
380 WINPR_ASSERT(operation);
382 status = smartcard_unpack_control_call(s, &operation->call.control);
392 WINPR_ASSERT(operation);
394 status = smartcard_unpack_get_attrib_call(s, &operation->call.getAttrib);
404 WINPR_ASSERT(operation);
406 status = smartcard_unpack_set_attrib_call(s, &operation->call.setAttrib);
414 WINPR_ASSERT(operation);
416 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
417 return SCARD_F_INTERNAL_ERROR;
419 Stream_Read_INT32(s, operation->call.lng.LongValue);
421 return SCARD_S_SUCCESS;
429 WINPR_ASSERT(operation);
431 status = smartcard_unpack_locate_cards_by_atr_a_call(s, &operation->call.locateCardsByATRA);
441 WINPR_ASSERT(operation);
443 status = smartcard_unpack_locate_cards_by_atr_w_call(s, &operation->call.locateCardsByATRW);
453 WINPR_ASSERT(operation);
455 status = smartcard_unpack_read_cache_a_call(s, &operation->call.readCacheA);
465 WINPR_ASSERT(operation);
467 status = smartcard_unpack_read_cache_w_call(s, &operation->call.readCacheW);
477 WINPR_ASSERT(operation);
479 status = smartcard_unpack_write_cache_a_call(s, &operation->call.writeCacheA);
489 WINPR_ASSERT(operation);
491 status = smartcard_unpack_write_cache_w_call(s, &operation->call.writeCacheW);
501 WINPR_ASSERT(operation);
503 status = smartcard_unpack_get_transmit_count_call(s, &operation->call.getTransmitCount);
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;
522 WINPR_ASSERT(operation);
524 status = smartcard_unpack_get_reader_icon_call(s, &operation->call.getReaderIcon);
534 WINPR_ASSERT(operation);
536 status = smartcard_unpack_get_device_type_id_call(s, &operation->call.getDeviceTypeId);
541LONG smartcard_irp_device_control_decode(
wStream* s, UINT32 CompletionId, UINT32 FileId,
544 return smartcard_irp_device_control_decode_request(s, CompletionId, FileId, operation);
547LONG smartcard_irp_device_control_decode_request(
wStream* s, UINT32 CompletionId, UINT32 FileId,
554 WINPR_ASSERT(operation);
558 if (!Stream_CheckAndLogRequiredLength(TAG, s, RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH))
559 return SCARD_F_INTERNAL_ERROR;
561 const UINT32 outputBufferLength = Stream_Get_UINT32(s);
562 const UINT32 inputBufferLength = Stream_Get_UINT32(s);
563 const UINT32 ioControlCode = Stream_Get_UINT32(s);
565 operation->ioControlCode = ioControlCode;
566 operation->ioControlCodeName = scard_get_ioctl_string(ioControlCode, FALSE);
567 operation->outputBufferLength = outputBufferLength;
569 if (Stream_Length(s) != (Stream_GetPosition(s) + inputBufferLength))
571 WLog_WARN(TAG,
"InputBufferLength mismatch: Actual: %" PRIuz
" Expected: %" PRIuz
"",
572 Stream_Length(s), Stream_GetPosition(s) + inputBufferLength);
573 return SCARD_F_INTERNAL_ERROR;
576 WLog_DBG(TAG,
"%s (0x%08" PRIX32
") FileId: %" PRIu32
" CompletionId: %" PRIu32
"",
577 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, FileId, CompletionId);
579 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
580 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
582 status = smartcard_unpack_common_type_header(s);
583 if (status != SCARD_S_SUCCESS)
586 status = smartcard_unpack_private_type_header(s);
587 if (status != SCARD_S_SUCCESS)
592 switch (ioControlCode)
594 case SCARD_IOCTL_ESTABLISHCONTEXT:
595 status = smartcard_EstablishContext_decode_request(s, operation);
598 case SCARD_IOCTL_RELEASECONTEXT:
599 status = smartcard_ReleaseContext_decode_request(s, operation);
602 case SCARD_IOCTL_ISVALIDCONTEXT:
603 status = smartcard_IsValidContext_decode_request(s, operation);
606 case SCARD_IOCTL_LISTREADERGROUPSA:
607 status = smartcard_ListReaderGroupsA_decode_request(s, operation);
610 case SCARD_IOCTL_LISTREADERGROUPSW:
611 status = smartcard_ListReaderGroupsW_decode_request(s, operation);
614 case SCARD_IOCTL_LISTREADERSA:
615 status = smartcard_ListReadersA_decode_request(s, operation);
618 case SCARD_IOCTL_LISTREADERSW:
619 status = smartcard_ListReadersW_decode_request(s, operation);
622 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
623 status = smartcard_ContextAndStringA_decode_request(s, operation);
626 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
627 status = smartcard_ContextAndStringW_decode_request(s, operation);
630 case SCARD_IOCTL_FORGETREADERGROUPA:
631 status = smartcard_ContextAndStringA_decode_request(s, operation);
634 case SCARD_IOCTL_FORGETREADERGROUPW:
635 status = smartcard_ContextAndStringW_decode_request(s, operation);
638 case SCARD_IOCTL_INTRODUCEREADERA:
639 status = smartcard_ContextAndTwoStringA_decode_request(s, operation);
642 case SCARD_IOCTL_INTRODUCEREADERW:
643 status = smartcard_ContextAndTwoStringW_decode_request(s, operation);
646 case SCARD_IOCTL_FORGETREADERA:
647 status = smartcard_ContextAndStringA_decode_request(s, operation);
650 case SCARD_IOCTL_FORGETREADERW:
651 status = smartcard_ContextAndStringW_decode_request(s, operation);
654 case SCARD_IOCTL_ADDREADERTOGROUPA:
655 status = smartcard_ContextAndTwoStringA_decode_request(s, operation);
658 case SCARD_IOCTL_ADDREADERTOGROUPW:
659 status = smartcard_ContextAndTwoStringW_decode_request(s, operation);
662 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
663 status = smartcard_ContextAndTwoStringA_decode_request(s, operation);
666 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
667 status = smartcard_ContextAndTwoStringW_decode_request(s, operation);
670 case SCARD_IOCTL_LOCATECARDSA:
671 status = smartcard_LocateCardsA_decode_request(s, operation);
674 case SCARD_IOCTL_LOCATECARDSW:
675 status = smartcard_LocateCardsW_decode_request(s, operation);
678 case SCARD_IOCTL_GETSTATUSCHANGEA:
679 status = smartcard_GetStatusChangeA_decode_request(s, operation);
682 case SCARD_IOCTL_GETSTATUSCHANGEW:
683 status = smartcard_GetStatusChangeW_decode_request(s, operation);
686 case SCARD_IOCTL_CANCEL:
687 status = smartcard_Cancel_decode_request(s, operation);
690 case SCARD_IOCTL_CONNECTA:
691 status = smartcard_ConnectA_decode_request(s, operation);
694 case SCARD_IOCTL_CONNECTW:
695 status = smartcard_ConnectW_decode_request(s, operation);
698 case SCARD_IOCTL_RECONNECT:
699 status = smartcard_Reconnect_decode_request(s, operation);
702 case SCARD_IOCTL_DISCONNECT:
703 status = smartcard_Disconnect_decode_request(s, operation);
706 case SCARD_IOCTL_BEGINTRANSACTION:
707 status = smartcard_BeginTransaction_decode_request(s, operation);
710 case SCARD_IOCTL_ENDTRANSACTION:
711 status = smartcard_EndTransaction_decode_request(s, operation);
714 case SCARD_IOCTL_STATE:
715 status = smartcard_State_decode_request(s, operation);
718 case SCARD_IOCTL_STATUSA:
719 status = smartcard_StatusA_decode_request(s, operation);
722 case SCARD_IOCTL_STATUSW:
723 status = smartcard_StatusW_decode_request(s, operation);
726 case SCARD_IOCTL_TRANSMIT:
727 status = smartcard_Transmit_decode_request(s, operation);
730 case SCARD_IOCTL_CONTROL:
731 status = smartcard_Control_decode_request(s, operation);
734 case SCARD_IOCTL_GETATTRIB:
735 status = smartcard_GetAttrib_decode_request(s, operation);
738 case SCARD_IOCTL_SETATTRIB:
739 status = smartcard_SetAttrib_decode_request(s, operation);
742 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
743 status = smartcard_AccessStartedEvent_decode_request(s, operation);
746 case SCARD_IOCTL_LOCATECARDSBYATRA:
747 status = smartcard_LocateCardsByATRA_decode_request(s, operation);
750 case SCARD_IOCTL_LOCATECARDSBYATRW:
751 status = smartcard_LocateCardsByATRW_decode_request(s, operation);
754 case SCARD_IOCTL_READCACHEA:
755 status = smartcard_ReadCacheA_decode_request(s, operation);
758 case SCARD_IOCTL_READCACHEW:
759 status = smartcard_ReadCacheW_decode_request(s, operation);
762 case SCARD_IOCTL_WRITECACHEA:
763 status = smartcard_WriteCacheA_decode_request(s, operation);
766 case SCARD_IOCTL_WRITECACHEW:
767 status = smartcard_WriteCacheW_decode_request(s, operation);
770 case SCARD_IOCTL_GETTRANSMITCOUNT:
771 status = smartcard_GetTransmitCount_decode_request(s, operation);
774 case SCARD_IOCTL_RELEASETARTEDEVENT:
775 status = smartcard_ReleaseStartedEvent_decode_request(s, operation);
778 case SCARD_IOCTL_GETREADERICON:
779 status = smartcard_GetReaderIcon_decode_request(s, operation);
782 case SCARD_IOCTL_GETDEVICETYPEID:
783 status = smartcard_GetDeviceTypeId_decode_request(s, operation);
787 status = SCARD_F_INTERNAL_ERROR;
791 smartcard_call_to_operation_handle(operation);
793 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
794 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
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;
801 if (Stream_GetPosition(s) < Stream_Length(s))
803 size_t difference = 0;
804 difference = Stream_Length(s) - Stream_GetPosition(s);
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);
814 if (Stream_GetPosition(s) > Stream_Length(s))
816 size_t difference = 0;
817 difference = Stream_GetPosition(s) - Stream_Length(s);
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);
831 WINPR_ASSERT(operation);
833 return smartcard_unpack_establish_context_return(s, &operation->
ret.establishContext);
839 WINPR_ASSERT(operation);
842 smartcard_trace_long_return(&ret,
"ReleaseContext");
843 return SCARD_S_SUCCESS;
849 WINPR_ASSERT(operation);
852 smartcard_trace_long_return(&ret,
"IsValidContext");
853 return SCARD_S_SUCCESS;
859 WINPR_ASSERT(operation);
861 return smartcard_unpack_list_reader_groups_return(s, &operation->
ret.listReaders, FALSE);
867 WINPR_ASSERT(operation);
869 return smartcard_unpack_list_reader_groups_return(s, &operation->
ret.listReaders, TRUE);
875 WINPR_ASSERT(operation);
877 return smartcard_unpack_list_readers_return(s, &operation->
ret.listReaders, FALSE);
883 WINPR_ASSERT(operation);
885 return smartcard_unpack_list_readers_return(s, &operation->
ret.listReaders, TRUE);
891 WINPR_ASSERT(operation);
893 return smartcard_unpack_get_status_change_return(s, &operation->
ret.getStatusChange, FALSE);
899 WINPR_ASSERT(operation);
901 return smartcard_unpack_get_status_change_return(s, &operation->
ret.getStatusChange, TRUE);
907 WINPR_ASSERT(operation);
910 smartcard_trace_long_return(&ret,
"Cancel");
911 return SCARD_S_SUCCESS;
917 WINPR_ASSERT(operation);
919 return smartcard_unpack_connect_return(s, &operation->
ret.connect);
925 WINPR_ASSERT(operation);
927 return smartcard_unpack_connect_return(s, &operation->
ret.connect);
933 WINPR_ASSERT(operation);
935 return smartcard_unpack_reconnect_return(s, &operation->
ret.reconnect);
941 WINPR_ASSERT(operation);
944 smartcard_trace_long_return(&ret,
"Disconnect");
945 return SCARD_S_SUCCESS;
951 WINPR_ASSERT(operation);
954 smartcard_trace_long_return(&ret,
"BeginTransaction");
955 return SCARD_S_SUCCESS;
961 WINPR_ASSERT(operation);
964 smartcard_trace_long_return(&ret,
"EndTransaction");
965 return SCARD_S_SUCCESS;
971 WINPR_ASSERT(operation);
973 return smartcard_unpack_status_return(s, &operation->
ret.status, FALSE);
979 WINPR_ASSERT(operation);
981 return smartcard_unpack_status_return(s, &operation->
ret.status, TRUE);
987 WINPR_ASSERT(operation);
989 return smartcard_unpack_transmit_return(s, &operation->
ret.transmit);
995 WINPR_ASSERT(operation);
997 return smartcard_unpack_control_return(s, &operation->
ret.control);
1003 WINPR_ASSERT(operation);
1005 return smartcard_unpack_get_attrib_return(s, &operation->
ret.getAttrib);
1011 WINPR_ASSERT(operation);
1014 smartcard_trace_long_return(&ret,
"SetAttrib");
1015 return SCARD_S_SUCCESS;
1018LONG smartcard_irp_device_control_decode_response(
wStream* s, UINT32 ioControlCode,
1021 LONG status = SCARD_S_SUCCESS;
1024 WINPR_ASSERT(operation);
1026 if (!Stream_CheckAndLogRequiredLength(TAG, s, RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH))
1027 return SCARD_F_INTERNAL_ERROR;
1029 const size_t startPosition = Stream_GetPosition(s);
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;
1036 if (outputBufferLength == 0)
1037 return SCARD_S_SUCCESS;
1039 if (!Stream_CheckAndLogRequiredLength(TAG, s, outputBufferLength))
1040 return SCARD_F_INTERNAL_ERROR;
1042 status = smartcard_unpack_common_type_header(s);
1043 if (status != SCARD_S_SUCCESS)
1046 status = smartcard_unpack_private_type_header(s);
1047 if (status != SCARD_S_SUCCESS)
1050 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1051 return SCARD_F_INTERNAL_ERROR;
1055 if (operation->
returnCode != SCARD_S_SUCCESS)
1057 WLog_DBG(TAG,
"%s failed with ReturnCode %s [0x%08" PRIX32
"]",
1058 scard_get_ioctl_string(ioControlCode, TRUE),
1062 switch (ioControlCode)
1064 case SCARD_IOCTL_ESTABLISHCONTEXT:
1065 status = smartcard_EstablishContext_decode_response(s, operation);
1068 case SCARD_IOCTL_RELEASECONTEXT:
1069 status = smartcard_ReleaseContext_decode_response(s, operation);
1072 case SCARD_IOCTL_ISVALIDCONTEXT:
1073 status = smartcard_IsValidContext_decode_response(s, operation);
1076 case SCARD_IOCTL_LISTREADERGROUPSA:
1077 status = smartcard_ListReaderGroupsA_decode_response(s, operation);
1080 case SCARD_IOCTL_LISTREADERGROUPSW:
1081 status = smartcard_ListReaderGroupsW_decode_response(s, operation);
1084 case SCARD_IOCTL_LISTREADERSA:
1085 status = smartcard_ListReadersA_decode_response(s, operation);
1088 case SCARD_IOCTL_LISTREADERSW:
1089 status = smartcard_ListReadersW_decode_response(s, operation);
1092 case SCARD_IOCTL_GETSTATUSCHANGEA:
1093 status = smartcard_GetStatusChangeA_decode_response(s, operation);
1096 case SCARD_IOCTL_GETSTATUSCHANGEW:
1097 status = smartcard_GetStatusChangeW_decode_response(s, operation);
1100 case SCARD_IOCTL_CANCEL:
1101 status = smartcard_Cancel_decode_response(s, operation);
1104 case SCARD_IOCTL_CONNECTA:
1105 status = smartcard_ConnectA_decode_response(s, operation);
1108 case SCARD_IOCTL_CONNECTW:
1109 status = smartcard_ConnectW_decode_response(s, operation);
1112 case SCARD_IOCTL_RECONNECT:
1113 status = smartcard_Reconnect_decode_response(s, operation);
1116 case SCARD_IOCTL_DISCONNECT:
1117 status = smartcard_Disconnect_decode_response(s, operation);
1120 case SCARD_IOCTL_BEGINTRANSACTION:
1121 status = smartcard_BeginTransaction_decode_response(s, operation);
1124 case SCARD_IOCTL_ENDTRANSACTION:
1125 status = smartcard_EndTransaction_decode_response(s, operation);
1128 case SCARD_IOCTL_STATUSA:
1129 status = smartcard_StatusA_decode_response(s, operation);
1132 case SCARD_IOCTL_STATUSW:
1133 status = smartcard_StatusW_decode_response(s, operation);
1136 case SCARD_IOCTL_TRANSMIT:
1137 status = smartcard_Transmit_decode_response(s, operation);
1140 case SCARD_IOCTL_CONTROL:
1141 status = smartcard_Control_decode_response(s, operation);
1144 case SCARD_IOCTL_GETATTRIB:
1145 status = smartcard_GetAttrib_decode_response(s, operation);
1148 case SCARD_IOCTL_SETATTRIB:
1149 status = smartcard_SetAttrib_decode_response(s, operation);
1153 WLog_WARN(TAG,
"unsupported response for %s (0x%08" PRIX32
")",
1154 scard_get_ioctl_string(ioControlCode, TRUE), ioControlCode);
1158 if (status != SCARD_S_SUCCESS)
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;
1168static LONG smartcard_EstablishContext_encode_request(
wStream* s,
1172 WINPR_ASSERT(operation);
1174 return smartcard_pack_establish_context_call(s, &operation->call.establishContext);
1177static LONG smartcard_ReleaseContext_encode_request(
wStream* s,
1181 WINPR_ASSERT(operation);
1183 return smartcard_pack_context_call(s, &operation->call.context,
"ReleaseContext");
1186static LONG smartcard_IsValidContext_encode_request(
wStream* s,
1190 WINPR_ASSERT(operation);
1192 return smartcard_pack_context_call(s, &operation->call.context,
"IsValidContext");
1195static LONG smartcard_ListReaderGroupsA_encode_request(
wStream* s,
1199 WINPR_ASSERT(operation);
1201 return smartcard_pack_list_reader_groups_call(s, &operation->call.listReaderGroups, FALSE);
1204static LONG smartcard_ListReaderGroupsW_encode_request(
wStream* s,
1208 WINPR_ASSERT(operation);
1210 return smartcard_pack_list_reader_groups_call(s, &operation->call.listReaderGroups, TRUE);
1216 WINPR_ASSERT(operation);
1218 return smartcard_pack_list_readers_call(s, &operation->call.listReaders, FALSE);
1224 WINPR_ASSERT(operation);
1226 return smartcard_pack_list_readers_call(s, &operation->call.listReaders, TRUE);
1229static LONG smartcard_GetStatusChangeA_encode_request(
wStream* s,
1233 WINPR_ASSERT(operation);
1235 return smartcard_pack_get_status_change_a_call(s, &operation->call.getStatusChangeA);
1238static LONG smartcard_GetStatusChangeW_encode_request(
wStream* s,
1242 WINPR_ASSERT(operation);
1244 return smartcard_pack_get_status_change_w_call(s, &operation->call.getStatusChangeW);
1250 WINPR_ASSERT(operation);
1252 return smartcard_pack_context_call(s, &operation->call.context,
"Cancel");
1258 WINPR_ASSERT(operation);
1260 return smartcard_pack_connect_a_call(s, &operation->call.connectA);
1266 WINPR_ASSERT(operation);
1268 return smartcard_pack_connect_w_call(s, &operation->call.connectW);
1274 WINPR_ASSERT(operation);
1276 return smartcard_pack_reconnect_call(s, &operation->call.reconnect);
1282 WINPR_ASSERT(operation);
1284 return smartcard_pack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
1288static LONG smartcard_BeginTransaction_encode_request(
wStream* s,
1292 WINPR_ASSERT(operation);
1294 return smartcard_pack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
1295 "BeginTransaction");
1298static LONG smartcard_EndTransaction_encode_request(
wStream* s,
1302 WINPR_ASSERT(operation);
1304 return smartcard_pack_hcard_and_disposition_call(s, &operation->call.hCardAndDisposition,
1311 WINPR_ASSERT(operation);
1313 return smartcard_pack_status_call(s, &operation->call.status, FALSE);
1319 WINPR_ASSERT(operation);
1321 return smartcard_pack_status_call(s, &operation->call.status, TRUE);
1327 WINPR_ASSERT(operation);
1329 return smartcard_pack_transmit_call(s, &operation->call.transmit);
1335 WINPR_ASSERT(operation);
1337 return smartcard_pack_control_call(s, &operation->call.control);
1343 WINPR_ASSERT(operation);
1345 return smartcard_pack_get_attrib_call(s, &operation->call.getAttrib);
1351 WINPR_ASSERT(operation);
1353 return smartcard_pack_set_attrib_call(s, &operation->call.setAttrib);
1358 LONG status = SCARD_S_SUCCESS;
1361 WINPR_ASSERT(operation);
1363 const UINT32 ioControlCode = operation->ioControlCode;
1365 const size_t headerPos = Stream_GetPosition(s);
1366 Stream_Zero(s, SMARTCARD_COMMON_TYPE_HEADER_LENGTH);
1367 Stream_Zero(s, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH);
1369 switch (ioControlCode)
1371 case SCARD_IOCTL_ESTABLISHCONTEXT:
1372 status = smartcard_EstablishContext_encode_request(s, operation);
1375 case SCARD_IOCTL_RELEASECONTEXT:
1376 status = smartcard_ReleaseContext_encode_request(s, operation);
1379 case SCARD_IOCTL_ISVALIDCONTEXT:
1380 status = smartcard_IsValidContext_encode_request(s, operation);
1383 case SCARD_IOCTL_LISTREADERGROUPSA:
1384 status = smartcard_ListReaderGroupsA_encode_request(s, operation);
1387 case SCARD_IOCTL_LISTREADERGROUPSW:
1388 status = smartcard_ListReaderGroupsW_encode_request(s, operation);
1391 case SCARD_IOCTL_LISTREADERSA:
1392 status = smartcard_ListReadersA_encode_request(s, operation);
1395 case SCARD_IOCTL_LISTREADERSW:
1396 status = smartcard_ListReadersW_encode_request(s, operation);
1399 case SCARD_IOCTL_GETSTATUSCHANGEA:
1400 status = smartcard_GetStatusChangeA_encode_request(s, operation);
1403 case SCARD_IOCTL_GETSTATUSCHANGEW:
1404 status = smartcard_GetStatusChangeW_encode_request(s, operation);
1407 case SCARD_IOCTL_CANCEL:
1408 status = smartcard_Cancel_encode_request(s, operation);
1411 case SCARD_IOCTL_CONNECTA:
1412 status = smartcard_ConnectA_encode_request(s, operation);
1415 case SCARD_IOCTL_CONNECTW:
1416 status = smartcard_ConnectW_encode_request(s, operation);
1419 case SCARD_IOCTL_RECONNECT:
1420 status = smartcard_Reconnect_encode_request(s, operation);
1423 case SCARD_IOCTL_DISCONNECT:
1424 status = smartcard_Disconnect_encode_request(s, operation);
1427 case SCARD_IOCTL_BEGINTRANSACTION:
1428 status = smartcard_BeginTransaction_encode_request(s, operation);
1431 case SCARD_IOCTL_ENDTRANSACTION:
1432 status = smartcard_EndTransaction_encode_request(s, operation);
1435 case SCARD_IOCTL_STATUSA:
1436 status = smartcard_StatusA_encode_request(s, operation);
1439 case SCARD_IOCTL_STATUSW:
1440 status = smartcard_StatusW_encode_request(s, operation);
1443 case SCARD_IOCTL_TRANSMIT:
1444 status = smartcard_Transmit_encode_request(s, operation);
1447 case SCARD_IOCTL_CONTROL:
1448 status = smartcard_Control_encode_request(s, operation);
1451 case SCARD_IOCTL_GETATTRIB:
1452 status = smartcard_GetAttrib_encode_request(s, operation);
1455 case SCARD_IOCTL_SETATTRIB:
1456 status = smartcard_SetAttrib_encode_request(s, operation);
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;
1465 if (status != SCARD_S_SUCCESS)
1468 if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
1469 (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT))
1471 const LONG rc = smartcard_pack_write_size_align(s, Stream_GetPosition(s), 8);
1472 if (rc != SCARD_S_SUCCESS)
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;
1481 status = smartcard_pack_write_size_align(s, payloadSize, 8);
1482 if (status != SCARD_S_SUCCESS)
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);
1499 for (UINT32 x = 0; x < cReaders; x++)
1502 free(state->szReader);
1505 free(rgReaderStates);
1510 for (UINT32 x = 0; x < cReaders; x++)
1513 free(state->szReader);
1516 free(rgReaderStates);
1525 switch (op->ioControlCode)
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:
1545 case SCARD_IOCTL_LOCATECARDSA:
1548 free(call->mszCards);
1550 free_reader_states_a(call->rgReaderStates, call->cReaders);
1553 case SCARD_IOCTL_LOCATECARDSW:
1556 free(call->mszCards);
1558 free_reader_states_w(call->rgReaderStates, call->cReaders);
1561 case SCARD_IOCTL_LOCATECARDSBYATRA:
1565 free_reader_states_a(call->rgReaderStates, call->cReaders);
1568 case SCARD_IOCTL_LOCATECARDSBYATRW:
1571 free_reader_states_w(call->rgReaderStates, call->cReaders);
1574 case SCARD_IOCTL_FORGETREADERA:
1575 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
1576 case SCARD_IOCTL_FORGETREADERGROUPA:
1582 case SCARD_IOCTL_FORGETREADERW:
1583 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
1584 case SCARD_IOCTL_FORGETREADERGROUPW:
1590 case SCARD_IOCTL_INTRODUCEREADERA:
1591 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
1592 case SCARD_IOCTL_ADDREADERTOGROUPA:
1599 case SCARD_IOCTL_INTRODUCEREADERW:
1600 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
1601 case SCARD_IOCTL_ADDREADERTOGROUPW:
1608 case SCARD_IOCTL_LISTREADERSA:
1609 case SCARD_IOCTL_LISTREADERSW:
1612 free(call->mszGroups);
1615 case SCARD_IOCTL_GETSTATUSCHANGEA:
1618 free_reader_states_a(call->rgReaderStates, call->cReaders);
1621 case SCARD_IOCTL_GETSTATUSCHANGEW:
1624 free_reader_states_w(call->rgReaderStates, call->cReaders);
1627 case SCARD_IOCTL_GETREADERICON:
1630 free(call->szReaderName);
1633 case SCARD_IOCTL_GETDEVICETYPEID:
1636 free(call->szReaderName);
1639 case SCARD_IOCTL_CONNECTA:
1642 free(call->szReader);
1645 case SCARD_IOCTL_CONNECTW:
1648 free(call->szReader);
1651 case SCARD_IOCTL_SETATTRIB:
1652 free(op->call.setAttrib.pbAttr);
1654 case SCARD_IOCTL_TRANSMIT:
1657 free(call->pbSendBuffer);
1658 free(call->pioSendPci);
1659 free(call->pioRecvPci);
1662 case SCARD_IOCTL_CONTROL:
1665 free(call->pvInBuffer);
1668 case SCARD_IOCTL_READCACHEA:
1671 free(call->szLookupName);
1672 free(call->Common.CardIdentifier);
1675 case SCARD_IOCTL_READCACHEW:
1678 free(call->szLookupName);
1679 free(call->Common.CardIdentifier);
1682 case SCARD_IOCTL_WRITECACHEA:
1685 free(call->szLookupName);
1686 free(call->Common.CardIdentifier);
1687 free(call->Common.pbData);
1690 case SCARD_IOCTL_WRITECACHEW:
1693 free(call->szLookupName);
1694 free(call->Common.CardIdentifier);
1695 free(call->Common.pbData);
1703 switch (op->ioControlCode)
1705 case SCARD_IOCTL_LISTREADERSA:
1706 case SCARD_IOCTL_LISTREADERSW:
1707 case SCARD_IOCTL_LISTREADERGROUPSA:
1708 case SCARD_IOCTL_LISTREADERGROUPSW:
1714 case SCARD_IOCTL_STATUSA:
1715 case SCARD_IOCTL_STATUSW:
1718 free(ret->mszReaderNames);
1721 case SCARD_IOCTL_GETSTATUSCHANGEA:
1722 case SCARD_IOCTL_GETSTATUSCHANGEW:
1725 free(ret->rgReaderStates);
1728 case SCARD_IOCTL_TRANSMIT:
1731 free(ret->pbRecvBuffer);
1732 free(ret->pioRecvPci);
1735 case SCARD_IOCTL_CONTROL:
1738 free(call->pvOutBuffer);
1741 case SCARD_IOCTL_GETATTRIB:
union SMARTCARD_OPERATION::@30 ret