1use nom::{le_u8, le_u16, le_u32, IResult};
2use super::*;
3use super::stream::*;
4use crate::properties::types::{
5 color::{OleColor, parser::aligned_ole_color},
6 font::parser::parse_guid_and_font,
7 parser::{parse_size, parse_position},
8 string::{stream::CountOfBytesWithCompressionFlag, parser::parse_string},
9};
10use crate::controls::ole_site_concrete::parser::parse_ole_site_concrete;
11use crate::common::{VarFlags, VarType, parser::*};
12use std::convert::TryFrom;
13
14named!(pub parse_form_control_header<u16>,
15 do_parse!(
16 tag!([0x00, 0x04]) >>
17 byte_count: le_u16 >>
18 (byte_count)
19 )
20);
21
22named!(pub parse_site_class_info_header<u16>,
23 do_parse!(
24 tag!([0x00, 0x00]) >>
25 byte_count: le_u16 >>
26 (byte_count)
27 )
28);
29
30pub fn parse_site_class_info(input: &[u8]) -> IResult<&[u8], ClassTable> {
31 let mut offset: usize = 0;
32 do_parse!(input,
33 _cb_class_table: parse_site_class_info_header >>
34 mask: map_opt!(
35 call!(aligned_le_u32, &mut offset),
36 ClassInfoPropMask::from_bits
37 ) >>
38 class_table_flags: map!(cond!(
39 mask.contains(ClassInfoPropMask::CLASS_FLAGS),
40 map_opt!(call!(aligned_le_u16, &mut offset), ClsTableFlags::from_bits)
41 ), |x| x.unwrap_or(ClsTableFlags::empty())) >>
42 var_flags: map!(cond!(
43 mask.contains(ClassInfoPropMask::CLASS_FLAGS),
44 map_opt!(call!(aligned_le_u16, &mut offset), VarFlags::from_bits)
45 ), |x| x.unwrap_or(VarFlags::empty())) >>
46 count_of_methods: map!(cond!(
47 mask.contains(ClassInfoPropMask::COUNT_OF_METHODS),
48 call!(aligned_le_u32, &mut offset)
49 ), |x| x.unwrap_or(0x00000000)) >>
50 dispid_bind: map!(cond!(
51 mask.contains(ClassInfoPropMask::DISPID_BIND),
52 call!(aligned_le_u32, &mut offset)
53 ), |x| x.unwrap_or(0xFFFFFFFF)) >>
54 get_bind_index: map!(cond!(
55 mask.contains(ClassInfoPropMask::GET_BIND_INDEX),
56 call!(aligned_le_u16, &mut offset)
57 ), |x| x.unwrap_or(0x0000)) >>
58 put_bind_index: map!(cond!(
59 mask.contains(ClassInfoPropMask::PUT_BIND_INDEX),
60 call!(aligned_le_u16, &mut offset)
61 ), |x| x.unwrap_or(0x0000)) >>
62 bind_type: map!(cond!(
63 mask.contains(ClassInfoPropMask::BIND_TYPE),
64 map_opt!(
65 call!(aligned_le_u16, &mut offset),
66 VarType::from_u16
67 )
68 ), |x| x.unwrap_or(VarType::Empty)) >>
69 get_value_index: map!(cond!(
70 mask.contains(ClassInfoPropMask::GET_VALUE_INDEX),
71 call!(aligned_le_u16, &mut offset)
72 ), |x| x.unwrap_or(0x0000)) >>
73 put_value_index: map!(cond!(
74 mask.contains(ClassInfoPropMask::PUT_VALUE_INDEX),
75 call!(aligned_le_u16, &mut offset)
76 ), |x| x.unwrap_or(0x0000)) >>
77 value_type: map!(cond!(
78 mask.contains(ClassInfoPropMask::VALUE_TYPE),
79 map_opt!(
80 call!(aligned_le_u16, &mut offset),
81 VarType::from_u16
82 )
83 ), |x| x.unwrap_or(VarType::Empty)) >>
84 dispid_rowset: map!(cond!(
85 mask.contains(ClassInfoPropMask::DISPID_ROWSET),
86 call!(aligned_le_u32, &mut offset)
87 ), |x| x.unwrap_or(0xFFFFFFFF)) >>
88 set_rowset: map!(cond!(
89 mask.contains(ClassInfoPropMask::SET_ROWSET),
90 call!(aligned_le_u16, &mut offset)
91 ), |x| x.unwrap_or(0x0000)) >>
92 call!(align, &mut offset, 4) >>
93 cls_id: map!(cond!(
94 mask.contains(ClassInfoPropMask::CLS_ID),
95 parse_guid
96 ), |x| x.unwrap_or(GUID::EMPTY)) >>
97 disp_event: map!(cond!(
98 mask.contains(ClassInfoPropMask::DISP_EVENT),
99 parse_guid
100 ), |x| x.unwrap_or(GUID::DEFAULT)) >>
101 default_proc: map!(cond!(
102 mask.contains(ClassInfoPropMask::DEFAULT_PROC),
103 parse_guid
104 ), |x| x.unwrap_or(GUID::DEFAULT)) >>
105 (ClassTable{
106 class_table_flags, var_flags, count_of_methods,
107 dispid_bind,
108 get_bind_index, put_bind_index, bind_type,
109 get_value_index, put_value_index, value_type,
110 dispid_rowset, set_rowset,
111 cls_id, disp_event, default_proc,
112 })
113 )
114}
115
116named_args!(pub parse_form_object_depth_type_count<'a>(offset: &'a mut usize)<(u8, SiteType, u32)>,
117 do_parse!(
118 depth: le_u8 >>
119 value: map_opt!(le_u8, TypeOrCount::from_bits) >>
120 type_or_count: value!((value & TypeOrCount::TYPE_OR_COUNT).bits()) >>
121 is_count: value!(value.contains(TypeOrCount::IS_COUNT)) >>
122 res: switch!(value!(is_count),
123 true => do_parse!(
124 r#type: map_opt!(le_u8, |x| { *offset += 3; SiteType::from_u8(x) }) >>
125 count: value!(u32::from(type_or_count)) >>
126 ((depth, r#type, count))
127 ) |
128 false => do_parse!(
129 r#type: map_opt!(value!(type_or_count), |x| { *offset += 2; SiteType::from_u8(x) }) >>
130 ((depth, r#type, 1))
131 )
132 ) >>
133 (res)
134 )
135);
136
137pub fn parse_site_depths_and_types(input: &[u8], count_of_sites: u32) -> IResult<&[u8], Vec<SiteDepthAndType>> {
138 let mut site_count: u32 = 0;
139 let mut offset: usize = 0;
140 let (input, ucount) = map_res!(input, value!(site_count), usize::try_from)?;
141 let mut data = input;
142 let mut result = Vec::with_capacity(ucount);
143 while site_count < count_of_sites {
144 let (rest, (depth, r#type, count)) = parse_form_object_depth_type_count(data, &mut offset)?;
145 site_count += count;
146 let depth_and_type = SiteDepthAndType{depth, r#type};
147 for _i in 0..count {
148 result.push(depth_and_type);
149 }
150 data = rest;
151 }
152 let (rest, _) = align(data, &mut offset, 4)?;
153 Ok((rest, result))
154}
155
156pub fn parse_sites(input: &[u8], site_depths_and_types: Vec<SiteDepthAndType>)
157-> IResult<&[u8], Vec<Site>> {
158 let mut result = Vec::with_capacity(site_depths_and_types.len());
159 let mut data = input;
160 for site_depth_and_type in site_depths_and_types {
161 let (rest, site) = match site_depth_and_type.r#type {
162 SiteType::Ole => parse_ole_site_concrete(data).map(|(r,x)| (r, Site::Ole(x)))?
163 };
164 result.push(site);
165 data = rest;
166 }
167 return Ok((data, result));
168}
169
170
171pub fn parse_form_control(input: &[u8]) -> IResult<&[u8], FormControl> {
172 let mut offset: usize = 0;
173 do_parse!(input,
174 _cb_form: parse_form_control_header >>
175 mask: map_opt!(
176 call!(aligned_le_u32, &mut offset),
177 FormPropMask::from_bits
178 ) >>
179 picture_tiling: value!(mask.contains(FormPropMask::PICTURE_TILING)) >>
180 back_color: map!(cond!(
181 mask.contains(FormPropMask::BACK_COLOR),
182 call!(aligned_ole_color, &mut offset)
183 ), |x| x.unwrap_or(OleColor::BTNFACE)) >>
184 fore_color: map!(cond!(
185 mask.contains(FormPropMask::FORE_COLOR),
186 call!(aligned_ole_color, &mut offset)
187 ), |x| x.unwrap_or(OleColor::BTNTEXT)) >>
188 next_available_id: map!(cond!(
189 mask.contains(FormPropMask::NEXT_AVAILABLE_ID),
190 call!(aligned_le_u32, &mut offset)
191 ), |x| x.unwrap_or(0x00000000)) >>
192 boolean_properties: map!(cond!(
193 mask.contains(FormPropMask::BOOLEAN_PROPERTIES),
194 map_opt!(call!(aligned_le_u32, &mut offset), FormFlags::from_bits)
195 ), |x| x.unwrap_or(FormFlags::ENABLED)) >>
196 border_style: map!(cond!(
197 mask.contains(FormPropMask::BORDER_STYLE),
198 map_opt!(call!(aligned_le_u8, &mut offset), BorderStyle::from_u8)
199 ), |x| x.unwrap_or(BorderStyle::None)) >>
200 mouse_pointer: map!(cond!(
201 mask.contains(FormPropMask::MOUSE_POINTER),
202 map_opt!(call!(aligned_le_u8, &mut offset), MousePointer::from_u8)
203 ), |x| x.unwrap_or(MousePointer::Default)) >>
204 scroll_bars: map!(cond!(
205 mask.contains(FormPropMask::SCROLL_BARS),
206 map_opt!(call!(aligned_le_u8, &mut offset), FormScrollBarFlags::from_bits)
207 ), |x| x.unwrap_or(FormScrollBarFlags::DEFAULT)) >>
208 group_count: map!(cond!(
209 mask.contains(FormPropMask::GROUP_CNT),
210 call!(aligned_le_u32, &mut offset)
211 ), |x| x.unwrap_or(0x00000000)) >>
212 _mouse_icon: map!(cond!(
213 mask.contains(FormPropMask::MOUSE_ICON),
214 verify!(call!(aligned_le_u16, &mut offset), |x: u16| x == 0xFFFF)
215 ), |x| x.unwrap_or(0)) >>
216 cycle: map!(cond!(
217 mask.contains(FormPropMask::CYCLE),
218 map_opt!(call!(aligned_le_u8, &mut offset), Cycle::from_u8)
219 ), |x| { x.unwrap_or(Cycle::AllForms)}) >>
220 special_effect: map!(cond!(
221 mask.contains(FormPropMask::SPECIAL_EFFECT),
222 map_opt!(call!(aligned_le_u8, &mut offset), SpecialEffect::from_u8)
223 ), |x| x.unwrap_or(SpecialEffect::Flat)) >>
224 border_color: map!(cond!(
225 mask.contains(FormPropMask::BORDER_COLOR),
226 call!(aligned_ole_color, &mut offset)
227 ), |x| x.unwrap_or(OleColor::BTNTEXT)) >>
228 length_and_compression: map!(cond!(
229 mask.contains(FormPropMask::CAPTION),
230 map_opt!(
231 call!(aligned_le_u32, &mut offset),
232 CountOfBytesWithCompressionFlag::from_bits
233 )
234 ), |x| x.unwrap_or(CountOfBytesWithCompressionFlag::EMPTY)) >>
235 _font: map!(cond!(
236 mask.contains(FormPropMask::FONT),
237 verify!(call!(aligned_le_u16, &mut offset), |x: u16| x == 0xFFFF)
238 ), |x| x.unwrap_or(0)) >>
239 _picture: map!(cond!(
240 mask.contains(FormPropMask::PICTURE),
241 verify!(call!(aligned_le_u16, &mut offset), |x: u16| x == 0xFFFF)
242 ), |x| x.unwrap_or(0)) >>
243 zoom: map!(cond!(
244 mask.contains(FormPropMask::ZOOM),
245 call!(aligned_le_u32, &mut offset)
246 ), |x| x.unwrap_or(100 as u32)) >>
247 picture_alignment: map!(cond!(
248 mask.contains(FormPropMask::PICTURE_ALIGNMENT),
249 map_opt!(
250 call!(aligned_le_u8, &mut offset),
251 PictureAlignment::from_u8
252 )
253 ), |x| x.unwrap_or(PictureAlignment::Center)) >>
254 picture_size_mode: map!(cond!(
255 mask.contains(FormPropMask::PICTURE_SIZE_MODE),
256 map_opt!(
257 call!(aligned_le_u8, &mut offset),
258 PictureSizeMode::from_u8
259 )
260 ), |x| x.unwrap_or(PictureSizeMode::Clip)) >>
261 shape_cookie: map!(cond!(
262 mask.contains(FormPropMask::SHAPE_COOKIE),
263 call!(aligned_le_u32, &mut offset)
264 ), |x| x.unwrap_or(0 as u32)) >>
265 draw_buffer: map!(cond!(
266 mask.contains(FormPropMask::DRAW_BUFFER),
267 call!(aligned_le_u32, &mut offset)
268 ), |x| x.unwrap_or(0 as u32)) >>
269 call!(align, &mut offset, 4) >>
270 displayed_size: map!(cond!(
271 mask.contains(FormPropMask::DISPLAYED_SIZE),
272 map!(parse_size, |x| { offset += 8; x})
273 ), |x| x.unwrap_or(Size{width: 4000, height: 3000})) >>
274 logical_size: map!(cond!(
275 mask.contains(FormPropMask::LOGICAL_SIZE),
276 map!(parse_size, |x| { offset += 8; x})
277 ), |x| x.unwrap_or(Size{width: 4000, height: 3000})) >>
278 scroll_position: map!(cond!(
279 mask.contains(FormPropMask::SCROLL_POSITION),
280 map!(parse_position, |x| { offset += 8; x})
281 ), |x| x.unwrap_or(Position{top: 0, left: 0})) >>
282 caption: map!(cond!(
283 mask.contains(FormPropMask::CAPTION),
284 call!(parse_string, length_and_compression)
285 ), |x| x.unwrap_or_else(|| "".to_string())) >>
286 mouse_icon: value!(GuidAndPicture::EMPTY) >>
288 font: map!(cond!(
289 mask.contains(FormPropMask::FONT),
290 parse_guid_and_font
291 ), |x| x.unwrap_or(GuidAndFont::EMPTY)) >>
292 picture: value!(GuidAndPicture::EMPTY) >>
294 count_of_site_class_info: map!(cond!(
295 !boolean_properties.contains(FormFlags::DONTSAVECLASSTABLE),
296 map_res!(le_u16, usize::try_from)
297 ), |x| x.unwrap_or(0)) >>
298 site_classes: count!(parse_site_class_info, count_of_site_class_info) >>
299 count_of_sites: le_u32 >>
301 _count_of_bytes: le_u32 >>
302 site_depths_and_types: call!(parse_site_depths_and_types, count_of_sites) >>
303 sites: call!(parse_sites, site_depths_and_types) >>
304 (FormControl{
306 back_color, fore_color, next_available_id, boolean_properties,
307 border_style, mouse_pointer, scroll_bars, group_count,
308 cycle, special_effect, border_color, zoom, draw_buffer,
309 picture_alignment, picture_size_mode, shape_cookie,
310 displayed_size, logical_size, scroll_position, caption,
311 mouse_icon, font, picture, picture_tiling,
312 sites, site_classes,
313 })
314 )
315}