pub mod ndr;
pub mod rpce;
use core::mem::size_of;
use bitflags::bitflags;
use ironrdp_core::{
cast_length, ensure_size, invalid_field_err, other_err, DecodeError, DecodeResult, EncodeResult, ReadCursor,
WriteCursor,
};
use ironrdp_pdu::utils::{
encoded_multistring_len, read_multistring_from_cursor, write_multistring_to_cursor, CharacterSet,
};
use super::efs::IoCtlCode;
use crate::pdu::esc::ndr::{Decode as _, Encode as _};
#[derive(Debug, PartialEq, Clone)]
pub enum ScardCall {
AccessStartedEventCall(ScardAccessStartedEventCall),
EstablishContextCall(EstablishContextCall),
ListReadersCall(ListReadersCall),
GetStatusChangeCall(GetStatusChangeCall),
ConnectCall(ConnectCall),
HCardAndDispositionCall(HCardAndDispositionCall),
TransmitCall(TransmitCall),
StatusCall(StatusCall),
ContextCall(ContextCall),
GetDeviceTypeIdCall(GetDeviceTypeIdCall),
ReadCacheCall(ReadCacheCall),
WriteCacheCall(WriteCacheCall),
GetReaderIconCall(GetReaderIconCall),
Unsupported,
}
impl ScardCall {
pub fn decode(io_ctl_code: ScardIoCtlCode, src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
match io_ctl_code {
ScardIoCtlCode::AccessStartedEvent => Ok(ScardCall::AccessStartedEventCall(
ScardAccessStartedEventCall::decode(src)?,
)),
ScardIoCtlCode::EstablishContext => Ok(ScardCall::EstablishContextCall(EstablishContextCall::decode(src)?)),
ScardIoCtlCode::ListReadersW => Ok(ScardCall::ListReadersCall(ListReadersCall::decode(
src,
Some(CharacterSet::Unicode),
)?)),
ScardIoCtlCode::ListReadersA => Ok(ScardCall::ListReadersCall(ListReadersCall::decode(
src,
Some(CharacterSet::Ansi),
)?)),
ScardIoCtlCode::GetStatusChangeW => Ok(ScardCall::GetStatusChangeCall(GetStatusChangeCall::decode(
src,
Some(CharacterSet::Unicode),
)?)),
ScardIoCtlCode::GetStatusChangeA => Ok(ScardCall::GetStatusChangeCall(GetStatusChangeCall::decode(
src,
Some(CharacterSet::Ansi),
)?)),
ScardIoCtlCode::ConnectW => Ok(ScardCall::ConnectCall(ConnectCall::decode(
src,
Some(CharacterSet::Unicode),
)?)),
ScardIoCtlCode::ConnectA => Ok(ScardCall::ConnectCall(ConnectCall::decode(
src,
Some(CharacterSet::Ansi),
)?)),
ScardIoCtlCode::BeginTransaction => Ok(ScardCall::HCardAndDispositionCall(
HCardAndDispositionCall::decode(src)?,
)),
ScardIoCtlCode::Transmit => Ok(ScardCall::TransmitCall(TransmitCall::decode(src)?)),
ScardIoCtlCode::StatusW | ScardIoCtlCode::StatusA => Ok(ScardCall::StatusCall(StatusCall::decode(src)?)),
ScardIoCtlCode::ReleaseContext => Ok(ScardCall::ContextCall(ContextCall::decode(src)?)),
ScardIoCtlCode::EndTransaction => Ok(ScardCall::HCardAndDispositionCall(HCardAndDispositionCall::decode(
src,
)?)),
ScardIoCtlCode::Disconnect => Ok(ScardCall::HCardAndDispositionCall(HCardAndDispositionCall::decode(
src,
)?)),
ScardIoCtlCode::Cancel => Ok(ScardCall::ContextCall(ContextCall::decode(src)?)),
ScardIoCtlCode::IsValidContext => Ok(ScardCall::ContextCall(ContextCall::decode(src)?)),
ScardIoCtlCode::GetDeviceTypeId => Ok(ScardCall::GetDeviceTypeIdCall(GetDeviceTypeIdCall::decode(src)?)),
ScardIoCtlCode::ReadCacheW => Ok(ScardCall::ReadCacheCall(ReadCacheCall::decode(
src,
Some(CharacterSet::Unicode),
)?)),
ScardIoCtlCode::ReadCacheA => Ok(ScardCall::ReadCacheCall(ReadCacheCall::decode(
src,
Some(CharacterSet::Ansi),
)?)),
ScardIoCtlCode::WriteCacheW => Ok(ScardCall::WriteCacheCall(WriteCacheCall::decode(
src,
Some(CharacterSet::Unicode),
)?)),
ScardIoCtlCode::WriteCacheA => Ok(ScardCall::WriteCacheCall(WriteCacheCall::decode(
src,
Some(CharacterSet::Ansi),
)?)),
ScardIoCtlCode::GetReaderIcon => Ok(ScardCall::GetReaderIconCall(GetReaderIconCall::decode(src)?)),
_ => {
warn!(?io_ctl_code, "Unsupported ScardIoCtlCode");
Ok(Self::Unsupported)
}
}
}
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct ScardContext {
pub value: u32,
}
impl ScardContext {
const VALUE_LENGTH: u32 = 4;
pub fn new(value: u32) -> Self {
Self { value }
}
}
impl ndr::Encode for ScardContext {
fn encode_ptr(&self, index: &mut u32, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ndr::encode_ptr(Some(Self::VALUE_LENGTH), index, dst)
}
fn encode_value(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: self.size_value());
dst.write_u32(Self::VALUE_LENGTH);
dst.write_u32(self.value);
Ok(())
}
fn size_ptr(&self) -> usize {
ndr::ptr_size(true)
}
fn size_value(&self) -> usize {
4 + 4 }
}
impl ndr::Decode for ScardContext {
fn decode_ptr(src: &mut ReadCursor<'_>, index: &mut u32) -> DecodeResult<Self>
where
Self: Sized,
{
ensure_size!(in: src, size: size_of::<u32>());
let length = src.read_u32();
if length != Self::VALUE_LENGTH {
error!(?length, "Unsupported value length in ScardContext");
return Err(invalid_field_err!(
"decode_ptr",
"unsupported value length in ScardContext"
));
}
let _ptr = ndr::decode_ptr(src, index)?;
Ok(Self { value: 0 })
}
fn decode_value(&mut self, src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<()> {
expect_no_charset(charset)?;
ensure_size!(in: src, size: size_of::<u32>() * 2);
let length = src.read_u32();
if length != Self::VALUE_LENGTH {
error!(?length, "Unsupported value length in ScardContext");
return Err(invalid_field_err!(
"decode_value",
"unsupported value length in ScardContext"
));
}
self.value = src.read_u32();
Ok(())
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct ReaderState {
pub reader: String,
pub common: ReaderStateCommonCall,
}
impl ndr::Decode for ReaderState {
fn decode_ptr(src: &mut ReadCursor<'_>, index: &mut u32) -> DecodeResult<Self> {
let _reader_ptr = ndr::decode_ptr(src, index)?;
let common = ReaderStateCommonCall::decode(src)?;
Ok(Self {
reader: String::new(),
common,
})
}
fn decode_value(&mut self, src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<()> {
let charset = expect_charset(charset)?;
self.reader = ndr::read_string_from_cursor(src, charset)?;
Ok(())
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(u32)]
pub enum ScardIoCtlCode {
EstablishContext = 0x0009_0014,
ReleaseContext = 0x0009_0018,
IsValidContext = 0x0009_001C,
ListReaderGroupsA = 0x0009_0020,
ListReaderGroupsW = 0x0009_0024,
ListReadersA = 0x0009_0028,
ListReadersW = 0x0009_002C,
IntroduceReaderGroupA = 0x0009_0050,
IntroduceReaderGroupW = 0x0009_0054,
ForgetReaderGroupA = 0x0009_0058,
ForgetReaderGroupW = 0x0009_005C,
IntroduceReaderA = 0x0009_0060,
IntroduceReaderW = 0x0009_0064,
ForgetReaderA = 0x0009_0068,
ForgetReaderW = 0x0009_006C,
AddReaderToGroupA = 0x0009_0070,
AddReaderToGroupW = 0x0009_0074,
RemoveReaderFromGroupA = 0x0009_0078,
RemoveReaderFromGroupW = 0x0009_007C,
LocateCardsA = 0x0009_0098,
LocateCardsW = 0x0009_009C,
GetStatusChangeA = 0x0009_00A0,
GetStatusChangeW = 0x0009_00A4,
Cancel = 0x0009_00A8,
ConnectA = 0x0009_00AC,
ConnectW = 0x0009_00B0,
Reconnect = 0x0009_00B4,
Disconnect = 0x0009_00B8,
BeginTransaction = 0x0009_00BC,
EndTransaction = 0x0009_00C0,
State = 0x0009_00C4,
StatusA = 0x0009_00C8,
StatusW = 0x0009_00CC,
Transmit = 0x0009_00D0,
Control = 0x0009_00D4,
GetAttrib = 0x0009_00D8,
SetAttrib = 0x0009_00DC,
AccessStartedEvent = 0x0009_00E0,
ReleaseTartedEvent = 0x0009_00E4,
LocateCardsByAtrA = 0x0009_00E8,
LocateCardsByAtrW = 0x0009_00EC,
ReadCacheA = 0x0009_00F0,
ReadCacheW = 0x0009_00F4,
WriteCacheA = 0x0009_00F8,
WriteCacheW = 0x0009_00FC,
GetTransmitCount = 0x0009_0100,
GetReaderIcon = 0x0009_0104,
GetDeviceTypeId = 0x0009_0108,
}
impl TryFrom<u32> for ScardIoCtlCode {
type Error = DecodeError;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0x0009_0014 => Ok(ScardIoCtlCode::EstablishContext),
0x0009_0018 => Ok(ScardIoCtlCode::ReleaseContext),
0x0009_001C => Ok(ScardIoCtlCode::IsValidContext),
0x0009_0020 => Ok(ScardIoCtlCode::ListReaderGroupsA),
0x0009_0024 => Ok(ScardIoCtlCode::ListReaderGroupsW),
0x0009_0028 => Ok(ScardIoCtlCode::ListReadersA),
0x0009_002C => Ok(ScardIoCtlCode::ListReadersW),
0x0009_0050 => Ok(ScardIoCtlCode::IntroduceReaderGroupA),
0x0009_0054 => Ok(ScardIoCtlCode::IntroduceReaderGroupW),
0x0009_0058 => Ok(ScardIoCtlCode::ForgetReaderGroupA),
0x0009_005C => Ok(ScardIoCtlCode::ForgetReaderGroupW),
0x0009_0060 => Ok(ScardIoCtlCode::IntroduceReaderA),
0x0009_0064 => Ok(ScardIoCtlCode::IntroduceReaderW),
0x0009_0068 => Ok(ScardIoCtlCode::ForgetReaderA),
0x0009_006C => Ok(ScardIoCtlCode::ForgetReaderW),
0x0009_0070 => Ok(ScardIoCtlCode::AddReaderToGroupA),
0x0009_0074 => Ok(ScardIoCtlCode::AddReaderToGroupW),
0x0009_0078 => Ok(ScardIoCtlCode::RemoveReaderFromGroupA),
0x0009_007C => Ok(ScardIoCtlCode::RemoveReaderFromGroupW),
0x0009_0098 => Ok(ScardIoCtlCode::LocateCardsA),
0x0009_009C => Ok(ScardIoCtlCode::LocateCardsW),
0x0009_00A0 => Ok(ScardIoCtlCode::GetStatusChangeA),
0x0009_00A4 => Ok(ScardIoCtlCode::GetStatusChangeW),
0x0009_00A8 => Ok(ScardIoCtlCode::Cancel),
0x0009_00AC => Ok(ScardIoCtlCode::ConnectA),
0x0009_00B0 => Ok(ScardIoCtlCode::ConnectW),
0x0009_00B4 => Ok(ScardIoCtlCode::Reconnect),
0x0009_00B8 => Ok(ScardIoCtlCode::Disconnect),
0x0009_00BC => Ok(ScardIoCtlCode::BeginTransaction),
0x0009_00C0 => Ok(ScardIoCtlCode::EndTransaction),
0x0009_00C4 => Ok(ScardIoCtlCode::State),
0x0009_00C8 => Ok(ScardIoCtlCode::StatusA),
0x0009_00CC => Ok(ScardIoCtlCode::StatusW),
0x0009_00D0 => Ok(ScardIoCtlCode::Transmit),
0x0009_00D4 => Ok(ScardIoCtlCode::Control),
0x0009_00D8 => Ok(ScardIoCtlCode::GetAttrib),
0x0009_00DC => Ok(ScardIoCtlCode::SetAttrib),
0x0009_00E0 => Ok(ScardIoCtlCode::AccessStartedEvent),
0x0009_00E4 => Ok(ScardIoCtlCode::ReleaseTartedEvent),
0x0009_00E8 => Ok(ScardIoCtlCode::LocateCardsByAtrA),
0x0009_00EC => Ok(ScardIoCtlCode::LocateCardsByAtrW),
0x0009_00F0 => Ok(ScardIoCtlCode::ReadCacheA),
0x0009_00F4 => Ok(ScardIoCtlCode::ReadCacheW),
0x0009_00F8 => Ok(ScardIoCtlCode::WriteCacheA),
0x0009_00FC => Ok(ScardIoCtlCode::WriteCacheW),
0x0009_0100 => Ok(ScardIoCtlCode::GetTransmitCount),
0x0009_0104 => Ok(ScardIoCtlCode::GetReaderIcon),
0x0009_0108 => Ok(ScardIoCtlCode::GetDeviceTypeId),
_ => {
error!("Unsupported ScardIoCtlCode: 0x{:08x}", value);
Err(invalid_field_err!("try_from", "ScardIoCtlCode", "unsupported value"))
}
}
}
}
impl IoCtlCode for ScardIoCtlCode {}
#[derive(Debug, PartialEq, Clone)]
pub struct ScardAccessStartedEventCall;
impl ScardAccessStartedEventCall {
pub fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
ironrdp_pdu::read_padding!(src, 4); Ok(Self)
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct LongReturn {
return_code: ReturnCode,
}
impl LongReturn {
const NAME: &'static str = "Long_Return";
pub fn new(return_code: ReturnCode) -> rpce::Pdu<Self> {
rpce::Pdu(Self { return_code })
}
}
impl rpce::HeaderlessEncode for LongReturn {
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: self.size());
dst.write_u32(self.return_code.into());
Ok(())
}
fn name(&self) -> &'static str {
Self::NAME
}
fn size(&self) -> usize {
self.return_code.size()
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
#[repr(u32)]
pub enum ReturnCode {
Success = 0x0000_0000,
InternalError = 0x8010_0001,
Cancelled = 0x8010_0002,
InvalidHandle = 0x8010_0003,
InvalidParameter = 0x8010_0004,
InvalidTarget = 0x8010_0005,
NoMemory = 0x8010_0006,
WaitedTooLong = 0x8010_0007,
InsufficientBuffer = 0x8010_0008,
UnknownReader = 0x8010_0009,
Timeout = 0x8010_000A,
SharingViolation = 0x8010_000B,
NoSmartcard = 0x8010_000C,
UnknownCard = 0x8010_000D,
CantDispose = 0x8010_000E,
ProtoMismatch = 0x8010_000F,
NotReady = 0x8010_0010,
InvalidValue = 0x8010_0011,
SystemCancelled = 0x8010_0012,
CommError = 0x8010_0013,
UnknownError = 0x8010_0014,
InvalidAtr = 0x8010_0015,
NotTransacted = 0x8010_0016,
ReaderUnavailable = 0x8010_0017,
Shutdown = 0x8010_0018,
PciTooSmall = 0x8010_0019,
IccInstallation = 0x8010_0020,
IccCreateorder = 0x8010_0021,
UnsupportedFeature = 0x8010_0022,
DirNotFound = 0x8010_0023,
FileNotFound = 0x8010_0024,
NoDir = 0x8010_0025,
ReaderUnsupported = 0x8010_001A,
DuplicateReader = 0x8010_001B,
CardUnsupported = 0x8010_001C,
NoService = 0x8010_001D,
ServiceStopped = 0x8010_001E,
Unexpected = 0x8010_001F,
NoFile = 0x8010_0026,
NoAccess = 0x8010_0027,
WriteTooMany = 0x8010_0028,
BadSeek = 0x8010_0029,
InvalidChv = 0x8010_002A,
UnknownResMsg = 0x8010_002B,
NoSuchCertificate = 0x8010_002C,
CertificateUnavailable = 0x8010_002D,
NoReadersAvailable = 0x8010_002E,
CommDataLost = 0x8010_002F,
NoKeyContainer = 0x8010_0030,
ServerTooBusy = 0x8010_0031,
PinCacheExpired = 0x8010_0032,
NoPinCache = 0x8010_0033,
ReadOnlyCard = 0x8010_0034,
UnsupportedCard = 0x8010_0065,
UnresponsiveCard = 0x8010_0066,
UnpoweredCard = 0x8010_0067,
ResetCard = 0x8010_0068,
RemovedCard = 0x8010_0069,
SecurityViolation = 0x8010_006A,
WrongChv = 0x8010_006B,
ChvBlocked = 0x8010_006C,
Eof = 0x8010_006D,
CancelledByUser = 0x8010_006E,
CardNotAuthenticated = 0x8010_006F,
CacheItemNotFound = 0x8010_0070,
CacheItemStale = 0x8010_0071,
CacheItemTooBig = 0x8010_0072,
}
impl ReturnCode {
pub fn size(&self) -> usize {
size_of::<u32>()
}
}
impl From<ReturnCode> for u32 {
fn from(val: ReturnCode) -> Self {
val as u32
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct EstablishContextCall {
pub scope: Scope,
}
impl EstablishContextCall {
pub fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
Ok(rpce::Pdu::<Self>::decode(src, None)?.into_inner())
}
fn size() -> usize {
size_of::<u32>()
}
}
impl rpce::HeaderlessDecode for EstablishContextCall {
fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
expect_no_charset(charset)?;
ensure_size!(in: src, size: Self::size());
let scope = Scope::try_from(src.read_u32())?;
Ok(Self { scope })
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
#[repr(u32)]
pub enum Scope {
User = 0x0000_0000,
Terminal = 0x0000_0001,
System = 0x0000_0002,
}
impl Scope {
pub fn size(&self) -> usize {
size_of::<u32>()
}
}
impl TryFrom<u32> for Scope {
type Error = DecodeError;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
0x0000_0000 => Ok(Scope::User),
0x0000_0001 => Ok(Scope::Terminal),
0x0000_0002 => Ok(Scope::System),
_ => {
error!("Unsupported Scope: 0x{:08x}", value);
Err(invalid_field_err!("try_from", "Scope", "unsupported value"))
}
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct EstablishContextReturn {
return_code: ReturnCode,
context: ScardContext,
}
impl EstablishContextReturn {
const NAME: &'static str = "EstablishContext_Return";
pub fn new(return_code: ReturnCode, context: ScardContext) -> rpce::Pdu<Self> {
rpce::Pdu(Self { return_code, context })
}
}
impl rpce::HeaderlessEncode for EstablishContextReturn {
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: self.size());
dst.write_u32(self.return_code.into());
let mut index = 0;
self.context.encode_ptr(&mut index, dst)?;
self.context.encode_value(dst)?;
Ok(())
}
fn name(&self) -> &'static str {
Self::NAME
}
fn size(&self) -> usize {
self.return_code.size() + self.context.size()
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct ListReadersCall {
pub context: ScardContext,
pub groups_ptr_length: u32,
pub groups_length: u32,
pub groups_ptr: u32,
pub groups: Vec<String>,
pub readers_is_null: bool, pub readers_size: u32,
}
impl ListReadersCall {
pub fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
Ok(rpce::Pdu::<Self>::decode(src, charset)?.into_inner())
}
}
impl rpce::HeaderlessDecode for ListReadersCall {
fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
let charset = expect_charset(charset)?;
let mut index = 0;
let mut context = ScardContext::decode_ptr(src, &mut index)?;
ensure_size!(in: src, size: size_of::<u32>());
let groups_ptr_length = src.read_u32();
let groups_ptr = ndr::decode_ptr(src, &mut index)?;
ensure_size!(in: src, size: size_of::<u32>() * 2);
let readers_is_null = (src.read_u32()) == 0x0000_0001;
let readers_size = src.read_u32();
context.decode_value(src, None)?;
if groups_ptr == 0 {
return Ok(Self {
context,
groups_ptr_length,
groups_ptr,
groups_length: 0,
groups: Vec::new(),
readers_is_null,
readers_size,
});
}
ensure_size!(in: src, size: size_of::<u32>());
let groups_length = src.read_u32();
if groups_length != groups_ptr_length {
return Err(invalid_field_err!(
"decode",
"mismatched reader groups length in NDR pointer and value"
));
}
let groups = read_multistring_from_cursor(src, charset)?;
Ok(Self {
context,
groups_ptr_length,
groups_ptr,
groups_length,
groups,
readers_is_null,
readers_size,
})
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct ListReadersReturn {
pub return_code: ReturnCode,
pub readers: Vec<String>,
}
impl ListReadersReturn {
const NAME: &'static str = "ListReaders_Return";
pub fn new(return_code: ReturnCode, readers: Vec<String>) -> rpce::Pdu<Self> {
rpce::Pdu(Self { return_code, readers })
}
}
impl rpce::HeaderlessEncode for ListReadersReturn {
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: self.size());
dst.write_u32(self.return_code.into());
let readers_length: u32 = cast_length!(
"ListReadersReturn",
"readers",
encoded_multistring_len(&self.readers, CharacterSet::Unicode)
)?;
let mut index = 0;
ndr::encode_ptr(Some(readers_length), &mut index, dst)?;
dst.write_u32(readers_length);
write_multistring_to_cursor(dst, &self.readers, CharacterSet::Unicode)?;
Ok(())
}
fn name(&self) -> &'static str {
Self::NAME
}
fn size(&self) -> usize {
self.return_code.size() + ndr::ptr_size(true) + 4 + encoded_multistring_len(&self.readers, CharacterSet::Unicode) }
}
#[derive(Debug, PartialEq, Clone)]
pub struct GetStatusChangeCall {
pub context: ScardContext,
pub timeout: u32,
pub states_ptr_length: u32,
pub states_ptr: u32,
pub states_length: u32,
pub states: Vec<ReaderState>,
}
impl GetStatusChangeCall {
pub fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
Ok(rpce::Pdu::<Self>::decode(src, charset)?.into_inner())
}
}
impl rpce::HeaderlessDecode for GetStatusChangeCall {
fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
let mut index = 0;
let mut context = ScardContext::decode_ptr(src, &mut index)?;
ensure_size!(in: src, size: size_of::<u32>() * 2);
let timeout = src.read_u32();
let states_ptr_length = src.read_u32();
let states_ptr = ndr::decode_ptr(src, &mut index)?;
context.decode_value(src, None)?;
ensure_size!(in: src, size: size_of::<u32>());
let states_length = src.read_u32();
let mut states = Vec::new();
for _ in 0..states_length {
let state = ReaderState::decode_ptr(src, &mut index)?;
states.push(state);
}
for state in states.iter_mut() {
state.decode_value(src, charset)?;
}
Ok(Self {
context,
timeout,
states_ptr_length,
states_ptr,
states_length,
states,
})
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct ReaderStateCommonCall {
pub current_state: CardStateFlags,
pub event_state: CardStateFlags,
pub atr_length: u32,
pub atr: [u8; 36],
}
impl ReaderStateCommonCall {
const FIXED_PART_SIZE: usize = size_of::<u32>() * 3 + 36 ;
fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
ensure_size!(in: src, size: Self::FIXED_PART_SIZE);
let current_state = CardStateFlags::from_bits_retain(src.read_u32());
let event_state = CardStateFlags::from_bits_retain(src.read_u32());
let atr_length = src.read_u32();
let atr = src.read_array::<36>();
Ok(Self {
current_state,
event_state,
atr_length,
atr,
})
}
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
dst.write_u32(self.current_state.bits());
dst.write_u32(self.event_state.bits());
dst.write_u32(self.atr_length);
dst.write_slice(&self.atr);
Ok(())
}
fn size() -> usize {
Self::FIXED_PART_SIZE
}
}
bitflags! {
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct CardStateFlags: u32 {
const SCARD_STATE_UNAWARE = 0x0000_0000;
const SCARD_STATE_IGNORE = 0x0000_0001;
const SCARD_STATE_CHANGED = 0x0000_0002;
const SCARD_STATE_UNKNOWN = 0x0000_0004;
const SCARD_STATE_UNAVAILABLE = 0x0000_0008;
const SCARD_STATE_EMPTY = 0x0000_0010;
const SCARD_STATE_PRESENT = 0x0000_0020;
const SCARD_STATE_ATRMATCH = 0x0000_0040;
const SCARD_STATE_EXCLUSIVE = 0x0000_0080;
const SCARD_STATE_INUSE = 0x0000_0100;
const SCARD_STATE_MUTE = 0x0000_0200;
const SCARD_STATE_UNPOWERED = 0x0000_0400;
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct GetStatusChangeReturn {
pub return_code: ReturnCode,
pub reader_states: Vec<ReaderStateCommonCall>,
}
impl GetStatusChangeReturn {
const NAME: &'static str = "GetStatusChange_Return";
pub fn new(return_code: ReturnCode, reader_states: Vec<ReaderStateCommonCall>) -> rpce::Pdu<Self> {
rpce::Pdu(Self {
return_code,
reader_states,
})
}
}
impl rpce::HeaderlessEncode for GetStatusChangeReturn {
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: self.size());
dst.write_u32(self.return_code.into());
let reader_states_len = cast_length!("GetStatusChangeReturn", "reader_states", self.reader_states.len())?;
let mut index = 0;
ndr::encode_ptr(Some(reader_states_len), &mut index, dst)?;
dst.write_u32(reader_states_len);
for reader_state in &self.reader_states {
reader_state.encode(dst)?;
}
Ok(())
}
fn name(&self) -> &'static str {
Self::NAME
}
fn size(&self) -> usize {
self.return_code.size() + ndr::ptr_size(true) + 4 + self.reader_states.iter().map(|_s| ReaderStateCommonCall::size()).sum::<usize>()
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct ConnectCall {
pub reader: String,
pub common: ConnectCommon,
}
impl ConnectCall {
pub fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
Ok(rpce::Pdu::<Self>::decode(src, charset)?.into_inner())
}
}
impl rpce::HeaderlessDecode for ConnectCall {
fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
let charset = expect_charset(charset)?;
let mut index = 0;
let _reader_ptr = ndr::decode_ptr(src, &mut index)?;
let mut common = ConnectCommon::decode_ptr(src, &mut index)?;
let reader = ndr::read_string_from_cursor(src, charset)?;
common.decode_value(src, None)?;
Ok(Self { reader, common })
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct ConnectCommon {
pub context: ScardContext,
pub share_mode: u32,
pub preferred_protocols: CardProtocol,
}
impl ndr::Decode for ConnectCommon {
fn decode_ptr(src: &mut ReadCursor<'_>, index: &mut u32) -> DecodeResult<Self>
where
Self: Sized,
{
let context = ScardContext::decode_ptr(src, index)?;
ensure_size!(in: src, size: size_of::<u32>() * 2);
let share_mode = src.read_u32();
let preferred_protocols = CardProtocol::from_bits_retain(src.read_u32());
Ok(Self {
context,
share_mode,
preferred_protocols,
})
}
fn decode_value(&mut self, src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<()> {
expect_no_charset(charset)?;
self.context.decode_value(src, None)
}
}
bitflags! {
#[derive(Debug, PartialEq, Clone)]
pub struct CardProtocol: u32 {
const SCARD_PROTOCOL_UNDEFINED = 0x0000_0000;
const SCARD_PROTOCOL_T0 = 0x0000_0001;
const SCARD_PROTOCOL_T1 = 0x0000_0002;
const SCARD_PROTOCOL_TX = 0x0000_0003;
const SCARD_PROTOCOL_RAW = 0x0001_0000;
const SCARD_PROTOCOL_DEFAULT = 0x8000_0000;
const SCARD_PROTOCOL_OPTIMAL = 0x0000_0000;
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct ScardHandle {
pub context: ScardContext,
pub value: u32,
}
impl ScardHandle {
const VALUE_LENGTH: u32 = 4;
pub fn new(context: ScardContext, value: u32) -> Self {
Self { context, value }
}
}
impl ndr::Decode for ScardHandle {
fn decode_ptr(src: &mut ReadCursor<'_>, index: &mut u32) -> DecodeResult<Self>
where
Self: Sized,
{
let context = ScardContext::decode_ptr(src, index)?;
ensure_size!(ctx: "ScardHandle::decode_ptr", in: src, size: size_of::<u32>());
let length = src.read_u32();
if length != Self::VALUE_LENGTH {
error!(?length, "Unsupported value length in ScardHandle");
return Err(invalid_field_err!(
"decode_ptr",
"unsupported value length in ScardHandle"
));
}
let _ptr = ndr::decode_ptr(src, index)?;
Ok(Self { context, value: 0 })
}
fn decode_value(&mut self, src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<()> {
expect_no_charset(charset)?;
self.context.decode_value(src, None)?;
ensure_size!(in: src, size: size_of::<u32>());
let length = src.read_u32();
if length != Self::VALUE_LENGTH {
error!(?length, "Unsupported value length in ScardHandle");
return Err(invalid_field_err!(
"decode_value",
"unsupported value length in ScardHandle"
));
}
ensure_size!(in: src, size: size_of::<u32>());
self.value = src.read_u32();
Ok(())
}
}
impl ndr::Encode for ScardHandle {
fn encode_ptr(&self, index: &mut u32, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
self.context.encode_ptr(index, dst)?;
ndr::encode_ptr(Some(Self::VALUE_LENGTH), index, dst)?;
Ok(())
}
fn encode_value(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: self.size_value());
self.context.encode_value(dst)?;
dst.write_u32(Self::VALUE_LENGTH);
dst.write_u32(self.value);
Ok(())
}
fn size_ptr(&self) -> usize {
self.context.size_ptr() + ndr::ptr_size(true)
}
fn size_value(&self) -> usize {
self.context.size_value() + 4 + 4 }
}
#[derive(Debug, PartialEq, Clone)]
pub struct ConnectReturn {
pub return_code: ReturnCode,
pub handle: ScardHandle,
pub active_protocol: CardProtocol,
}
impl ConnectReturn {
const NAME: &'static str = "Connect_Return";
pub fn new(return_code: ReturnCode, handle: ScardHandle, active_protocol: CardProtocol) -> rpce::Pdu<Self> {
rpce::Pdu(Self {
return_code,
handle,
active_protocol,
})
}
}
impl rpce::HeaderlessEncode for ConnectReturn {
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: self.size());
dst.write_u32(self.return_code.into());
let mut index = 0;
self.handle.encode_ptr(&mut index, dst)?;
dst.write_u32(self.active_protocol.bits());
self.handle.encode_value(dst)?;
Ok(())
}
fn name(&self) -> &'static str {
Self::NAME
}
fn size(&self) -> usize {
self.return_code.size() + self.handle.size() + 4 }
}
#[derive(Debug, PartialEq, Clone)]
pub struct HCardAndDispositionCall {
pub handle: ScardHandle,
pub disposition: u32,
}
impl HCardAndDispositionCall {
pub fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
Ok(rpce::Pdu::<Self>::decode(src, None)?.into_inner())
}
}
impl rpce::HeaderlessDecode for HCardAndDispositionCall {
fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
expect_no_charset(charset)?;
let mut index = 0;
let mut handle = ScardHandle::decode_ptr(src, &mut index)?;
ensure_size!(in: src, size: size_of::<u32>());
let disposition = src.read_u32();
handle.decode_value(src, None)?;
Ok(Self { handle, disposition })
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct TransmitCall {
pub handle: ScardHandle,
pub send_pci: SCardIORequest,
pub send_length: u32,
pub send_buffer: Vec<u8>,
pub recv_pci: Option<SCardIORequest>,
pub recv_buffer_is_null: bool,
pub recv_length: u32,
}
impl TransmitCall {
pub fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
Ok(rpce::Pdu::<Self>::decode(src, None)?.into_inner())
}
}
impl rpce::HeaderlessDecode for TransmitCall {
fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
expect_no_charset(charset)?;
let mut index = 0;
let mut handle = ScardHandle::decode_ptr(src, &mut index)?;
let mut send_pci = SCardIORequest::decode_ptr(src, &mut index)?;
ensure_size!(in: src, size: size_of::<u32>());
let _send_length = src.read_u32();
let _send_buffer_ptr = ndr::decode_ptr(src, &mut index)?;
let recv_pci_ptr = ndr::decode_ptr(src, &mut index)?;
ensure_size!(in: src, size: size_of::<u32>() * 2);
let recv_buffer_is_null = src.read_u32() == 1;
let recv_length = src.read_u32();
handle.decode_value(src, None)?;
send_pci.decode_value(src, None)?;
ensure_size!(in: src, size: size_of::<u32>());
let send_length = src.read_u32();
let send_length_usize: usize = cast_length!("TransmitCall", "send_length", send_length)?;
ensure_size!(in: src, size: send_length_usize);
let send_buffer = src.read_slice(send_length_usize).to_vec();
let recv_pci = if recv_pci_ptr != 0 {
let mut recv_pci = SCardIORequest::decode_ptr(src, &mut index)?;
recv_pci.decode_value(src, None)?;
Some(recv_pci)
} else {
None
};
Ok(Self {
handle,
send_pci,
send_length,
send_buffer,
recv_pci,
recv_buffer_is_null,
recv_length,
})
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct SCardIORequest {
pub protocol: CardProtocol,
pub extra_bytes_length: u32,
pub extra_bytes: Vec<u8>,
}
impl ndr::Decode for SCardIORequest {
fn decode_ptr(src: &mut ReadCursor<'_>, index: &mut u32) -> DecodeResult<Self>
where
Self: Sized,
{
ensure_size!(in: src, size: size_of::<u32>() * 2);
let protocol = CardProtocol::from_bits_retain(src.read_u32());
let extra_bytes_length = src.read_u32();
let _extra_bytes_ptr = ndr::decode_ptr(src, index)?;
let extra_bytes = Vec::new();
Ok(Self {
protocol,
extra_bytes_length,
extra_bytes,
})
}
fn decode_value(&mut self, src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<()> {
expect_no_charset(charset)?;
let extra_bytes_length: usize = cast_length!("TransmitCall", "extra_bytes_length", self.extra_bytes_length)?;
ensure_size!(in: src, size: extra_bytes_length);
self.extra_bytes = src.read_slice(extra_bytes_length).to_vec();
Ok(())
}
}
impl ndr::Encode for SCardIORequest {
fn encode_ptr(&self, index: &mut u32, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: self.size_ptr());
dst.write_u32(self.protocol.bits());
ndr::encode_ptr(Some(self.extra_bytes_length), index, dst)
}
fn encode_value(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: self.size_value());
dst.write_slice(&self.extra_bytes);
Ok(())
}
fn size_ptr(&self) -> usize {
4 + ndr::ptr_size(true)
}
fn size_value(&self) -> usize {
self.extra_bytes_length as usize
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct TransmitReturn {
pub return_code: ReturnCode,
pub recv_pci: Option<SCardIORequest>,
pub recv_buffer: Vec<u8>,
}
impl TransmitReturn {
const NAME: &'static str = "Transmit_Return";
pub fn new(return_code: ReturnCode, recv_pci: Option<SCardIORequest>, recv_buffer: Vec<u8>) -> rpce::Pdu<Self> {
rpce::Pdu(Self {
return_code,
recv_pci,
recv_buffer,
})
}
}
impl rpce::HeaderlessEncode for TransmitReturn {
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: self.size());
dst.write_u32(self.return_code.into());
let mut index = 0;
if let Some(recv_pci) = &self.recv_pci {
recv_pci.encode_ptr(&mut index, dst)?;
recv_pci.encode_value(dst)?;
} else {
dst.write_u32(0); }
let recv_buffer_len: u32 = cast_length!("TransmitReturn", "recv_buffer_len", self.recv_buffer.len())?;
ndr::encode_ptr(Some(recv_buffer_len), &mut index, dst)?;
dst.write_u32(recv_buffer_len);
dst.write_slice(&self.recv_buffer);
Ok(())
}
fn name(&self) -> &'static str {
Self::NAME
}
fn size(&self) -> usize {
self.return_code.size() + if let Some(recv_pci) = &self.recv_pci {
recv_pci.size()
} else {
4 }
+ ndr::ptr_size(true) + 4 + self.recv_buffer.len() }
}
#[derive(Debug, PartialEq, Clone)]
pub struct StatusCall {
pub handle: ScardHandle,
pub reader_names_is_null: bool,
pub reader_length: u32,
pub atr_length: u32,
}
impl StatusCall {
pub fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
Ok(rpce::Pdu::<Self>::decode(src, None)?.into_inner())
}
}
impl rpce::HeaderlessDecode for StatusCall {
fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
expect_no_charset(charset)?;
let mut index = 0;
let mut handle = ScardHandle::decode_ptr(src, &mut index)?;
ensure_size!(in: src, size: size_of::<u32>() * 3);
let reader_names_is_null = src.read_u32() == 1;
let reader_length = src.read_u32();
let atr_length = src.read_u32();
handle.decode_value(src, None)?;
Ok(Self {
handle,
reader_names_is_null,
reader_length,
atr_length,
})
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct StatusReturn {
pub return_code: ReturnCode,
pub reader_names: Vec<String>,
pub state: CardState,
pub protocol: CardProtocol,
pub atr: [u8; 32],
pub atr_length: u32,
pub encoding: CharacterSet,
}
impl StatusReturn {
const NAME: &'static str = "Status_Return";
pub fn new(
return_code: ReturnCode,
reader_names: Vec<String>,
state: CardState,
protocol: CardProtocol,
atr: [u8; 32],
atr_length: u32,
encoding: CharacterSet,
) -> rpce::Pdu<Self> {
rpce::Pdu(Self {
return_code,
reader_names,
state,
protocol,
atr,
atr_length,
encoding,
})
}
}
impl rpce::HeaderlessEncode for StatusReturn {
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: self.size());
dst.write_u32(self.return_code.into());
let mut index = 0;
let reader_names_length: u32 = cast_length!(
"StatusReturn",
"reader_names_length",
encoded_multistring_len(&self.reader_names, self.encoding)
)?;
ndr::encode_ptr(Some(reader_names_length), &mut index, dst)?;
dst.write_u32(self.state.into());
dst.write_u32(self.protocol.bits());
dst.write_slice(&self.atr);
dst.write_u32(self.atr_length);
dst.write_u32(reader_names_length);
write_multistring_to_cursor(dst, &self.reader_names, self.encoding)?;
Ok(())
}
fn name(&self) -> &'static str {
Self::NAME
}
fn size(&self) -> usize {
size_of::<u32>() * 5 + ndr::ptr_size(true) + self.atr.len() + encoded_multistring_len(&self.reader_names, self.encoding) }
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CardState {
Unknown = 0x0000_0000,
Absent = 0x0000_0001,
Present = 0x0000_0002,
Swallowed = 0x0000_0003,
Powered = 0x0000_0004,
Negotiable = 0x0000_0005,
SpecificMode = 0x0000_0006,
}
impl From<CardState> for u32 {
fn from(val: CardState) -> Self {
val as u32
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct ContextCall {
pub context: ScardContext,
}
impl ContextCall {
pub fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
Ok(rpce::Pdu::<Self>::decode(src, None)?.into_inner())
}
}
impl rpce::HeaderlessDecode for ContextCall {
fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
expect_no_charset(charset)?;
let mut index = 0;
let mut context = ScardContext::decode_ptr(src, &mut index)?;
context.decode_value(src, None)?;
Ok(Self { context })
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct GetDeviceTypeIdCall {
pub context: ScardContext,
pub reader_ptr: u32,
pub reader_name: String,
}
impl GetDeviceTypeIdCall {
pub fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
Ok(rpce::Pdu::<Self>::decode(src, None)?.into_inner())
}
}
impl rpce::HeaderlessDecode for GetDeviceTypeIdCall {
fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
expect_no_charset(charset)?;
let mut index = 0;
let mut context = ScardContext::decode_ptr(src, &mut index)?;
let reader_ptr = ndr::decode_ptr(src, &mut index)?;
context.decode_value(src, None)?;
let reader_name = ndr::read_string_from_cursor(src, CharacterSet::Unicode)?;
Ok(Self {
context,
reader_ptr,
reader_name,
})
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct GetDeviceTypeIdReturn {
pub return_code: ReturnCode,
pub device_type_id: u32,
}
impl GetDeviceTypeIdReturn {
const NAME: &'static str = "GetDeviceTypeId_Return";
pub fn new(return_code: ReturnCode, device_type_id: u32) -> rpce::Pdu<Self> {
rpce::Pdu(Self {
return_code,
device_type_id,
})
}
}
impl rpce::HeaderlessEncode for GetDeviceTypeIdReturn {
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: self.size());
dst.write_u32(self.return_code.into());
dst.write_u32(self.device_type_id);
Ok(())
}
fn name(&self) -> &'static str {
Self::NAME
}
fn size(&self) -> usize {
self.return_code.size() + size_of::<u32>() }
}
#[derive(Debug, PartialEq, Clone)]
pub struct ReadCacheCall {
pub lookup_name: String,
pub common: ReadCacheCommon,
}
impl ReadCacheCall {
pub fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
Ok(rpce::Pdu::<Self>::decode(src, charset)?.into_inner())
}
}
impl rpce::HeaderlessDecode for ReadCacheCall {
fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
let charset = expect_charset(charset)?;
let mut index = 0;
let _lookup_name_ptr = ndr::decode_ptr(src, &mut index)?;
let mut common = ReadCacheCommon::decode_ptr(src, &mut index)?;
let lookup_name = ndr::read_string_from_cursor(src, charset)?;
common.decode_value(src, None)?;
Ok(Self { lookup_name, common })
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct ReadCacheCommon {
pub context: ScardContext,
pub card_uuid: Vec<u8>,
pub freshness_counter: u32,
pub data_is_null: bool,
pub data_len: u32,
}
impl ndr::Decode for ReadCacheCommon {
fn decode_ptr(src: &mut ReadCursor<'_>, index: &mut u32) -> DecodeResult<Self>
where
Self: Sized,
{
let context = ScardContext::decode_ptr(src, index)?;
let _card_uuid_ptr = ndr::decode_ptr(src, index)?;
ensure_size!(in: src, size: size_of::<u32>() * 2 + size_of::<i32>());
let freshness_counter = src.read_u32();
let data_is_null = src.read_i32() == 1;
let data_len = src.read_u32();
Ok(Self {
context,
card_uuid: Vec::new(),
freshness_counter,
data_is_null,
data_len,
})
}
fn decode_value(&mut self, src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<()> {
expect_no_charset(charset)?;
self.context.decode_value(src, None)?;
ensure_size!(in: src, size: 16);
self.card_uuid = src.read_slice(16).to_vec();
Ok(())
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct ReadCacheReturn {
pub return_code: ReturnCode,
pub data: Vec<u8>,
}
impl ReadCacheReturn {
const NAME: &'static str = "ReadCache_Return";
pub fn new(return_code: ReturnCode, data: Vec<u8>) -> rpce::Pdu<Self> {
rpce::Pdu(Self { return_code, data })
}
}
impl rpce::HeaderlessEncode for ReadCacheReturn {
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: self.size());
dst.write_u32(self.return_code.into());
let mut index = 0;
let data_len: u32 = cast_length!("ReadCacheReturn", "data_len", self.data.len())?;
ndr::encode_ptr(Some(data_len), &mut index, dst)?;
dst.write_u32(data_len);
dst.write_slice(&self.data);
Ok(())
}
fn name(&self) -> &'static str {
Self::NAME
}
fn size(&self) -> usize {
self.return_code.size() + ndr::ptr_size(true) + size_of::<u32>() + self.data.len() }
}
#[derive(Debug, PartialEq, Clone)]
pub struct WriteCacheCall {
pub lookup_name: String,
pub common: WriteCacheCommon,
}
impl WriteCacheCall {
pub fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
Ok(rpce::Pdu::<Self>::decode(src, charset)?.into_inner())
}
}
impl rpce::HeaderlessDecode for WriteCacheCall {
fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
let charset = expect_charset(charset)?;
let mut index = 0;
let _lookup_name_ptr = ndr::decode_ptr(src, &mut index)?;
let mut common = WriteCacheCommon::decode_ptr(src, &mut index)?;
let lookup_name = ndr::read_string_from_cursor(src, charset)?;
common.decode_value(src, None)?;
Ok(Self { lookup_name, common })
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct WriteCacheCommon {
pub context: ScardContext,
pub card_uuid: Vec<u8>,
pub freshness_counter: u32,
pub data: Vec<u8>,
}
impl ndr::Decode for WriteCacheCommon {
fn decode_ptr(src: &mut ReadCursor<'_>, index: &mut u32) -> DecodeResult<Self>
where
Self: Sized,
{
let context = ScardContext::decode_ptr(src, index)?;
let _card_uuid_ptr = ndr::decode_ptr(src, index)?;
ensure_size!(in: src, size: size_of::<u32>() * 2);
let freshness_counter = src.read_u32();
let _data_len = src.read_u32();
let _data_ptr = ndr::decode_ptr(src, index)?;
Ok(Self {
context,
card_uuid: Vec::new(),
freshness_counter,
data: Vec::new(),
})
}
fn decode_value(&mut self, src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<()> {
expect_no_charset(charset)?;
self.context.decode_value(src, None)?;
ensure_size!(in: src, size: 16);
self.card_uuid = src.read_slice(16).to_vec();
ensure_size!(in: src, size: size_of::<u32>());
let data_len: usize = cast_length!("WriteCacheCommon", "data_len", src.read_u32())?;
ensure_size!(in: src, size: data_len);
self.data = src.read_slice(data_len).to_vec();
Ok(())
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct GetReaderIconCall {
pub context: ScardContext,
pub reader_name: String,
}
impl GetReaderIconCall {
pub fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
Ok(rpce::Pdu::<Self>::decode(src, None)?.into_inner())
}
}
impl rpce::HeaderlessDecode for GetReaderIconCall {
fn decode(src: &mut ReadCursor<'_>, charset: Option<CharacterSet>) -> DecodeResult<Self> {
expect_no_charset(charset)?;
let mut index = 0;
let mut context = ScardContext::decode_ptr(src, &mut index)?;
let _reader_ptr = ndr::decode_ptr(src, &mut index)?;
context.decode_value(src, None)?;
let reader_name = ndr::read_string_from_cursor(src, CharacterSet::Unicode)?;
Ok(Self { context, reader_name })
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct GetReaderIconReturn {
pub return_code: ReturnCode,
pub data: Vec<u8>,
}
impl GetReaderIconReturn {
const NAME: &'static str = "GetReaderIcon_Return";
pub fn new(return_code: ReturnCode, data: Vec<u8>) -> rpce::Pdu<Self> {
rpce::Pdu(Self { return_code, data })
}
}
impl rpce::HeaderlessEncode for GetReaderIconReturn {
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: self.size());
dst.write_u32(self.return_code.into());
let data_len: u32 = cast_length!("GetReaderIconReturn", "data_len", self.data.len())?;
let mut index = 0;
ndr::encode_ptr(Some(data_len), &mut index, dst)?;
dst.write_u32(data_len);
dst.write_slice(&self.data);
Ok(())
}
fn name(&self) -> &'static str {
Self::NAME
}
fn size(&self) -> usize {
size_of::<u32>() + ndr::ptr_size(true) + size_of::<u32>() + self.data.len() }
}
fn expect_charset(charset: Option<CharacterSet>) -> DecodeResult<CharacterSet> {
if charset.is_none() {
return Err(other_err!("internal error: missing character set"));
}
Ok(charset.unwrap())
}
fn expect_no_charset(charset: Option<CharacterSet>) -> DecodeResult<()> {
if charset.is_some() {
return Err(other_err!(
"internal error: character set given where none was expected"
));
}
Ok(())
}