1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use super::*;
pub struct Signature {
pub params: Vec<MethodParam>,
pub return_type: Option<Type>,
pub return_param: Option<Param>,
pub preserve_sig: bool,
}
#[derive(Clone)]
pub struct MethodParam {
pub def: Param,
pub ty: Type,
pub array_info: Option<ArrayInfo>,
}
impl Signature {
pub fn kind(&self) -> SignatureKind {
if self.preserve_sig {
return SignatureKind::PreserveSig;
}
if let Some(return_type) = &self.return_type {
match return_type {
Type::HRESULT => {
if self.params.len() >= 2 {
let guid = &self.params[self.params.len() - 2];
let object = &self.params[self.params.len() - 1];
if guid.ty == Type::ConstPtr((Box::new(Type::GUID), 1)) && !guid.def.flags().output() && object.ty == Type::MutPtr((Box::new(Type::Void), 2)) && object.def.is_com_out_ptr() {
if object.def.flags().optional() {
return SignatureKind::QueryOptional;
} else {
return SignatureKind::Query;
}
}
}
if self.params.last().map_or(false, |param| param.is_retval())
&& self.params[..self.params.len() - 1].iter().all(|param| {
let flags = param.def.flags();
flags.input() && !flags.output()
})
{
return SignatureKind::ResultValue;
}
return SignatureKind::ResultVoid;
}
Type::TypeDef(def) if def.type_name() == TypeName::NTSTATUS => {
return SignatureKind::ResultVoid;
}
_ if return_type.is_udt() => {
return SignatureKind::ReturnStruct;
}
_ => return SignatureKind::PreserveSig,
}
}
SignatureKind::ReturnVoid
}
pub fn size(&self) -> usize {
self.params.iter().fold(0, |sum, param| sum + param.ty.size())
}
pub(crate) fn combine_cfg(&self, cfg: &mut Cfg) {
self.return_type.iter().for_each(|def| def.combine_cfg(cfg));
self.params.iter().for_each(|def| def.ty.combine_cfg(cfg));
}
}
impl MethodParam {
fn is_retval(&self) -> bool {
if self.def.is_retval() {
return true;
}
if !self.ty.is_pointer() {
return false;
}
if self.ty.is_void() {
return false;
}
let flags = self.def.flags();
if flags.input() || !flags.output() || self.def.array_info().is_some() {
return false;
}
!self.ty.is_callback()
}
pub fn is_convertible(&self) -> bool {
self.def.flags().input() && !self.ty.is_winrt_array() && !self.ty.is_pointer() && self.ty.is_convertible() && self.def.array_info().is_none()
}
}