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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
mod console_data_block;
mod console_fe_data_block;
mod darwin_data_block;
mod environment_variable_data_block;
mod icon_environment_data_block;
mod known_folder_data_block;
mod property_store_data_block;
mod shim_data_block;
mod special_folder_data_block;
mod tracker_data_block;
mod vista_and_above_id_list_data_block;
use crate::{error::ExtraDataError, header::ShellLinkHeader};
use byteorder::{ReadBytesExt, LE};
pub use console_data_block::*;
pub use console_data_block::*;
pub use console_fe_data_block::*;
pub use darwin_data_block::*;
pub use environment_variable_data_block::*;
pub use icon_environment_data_block::*;
pub use known_folder_data_block::*;
pub use property_store_data_block::*;
pub use shim_data_block::*;
pub use special_folder_data_block::*;
use std::io::Cursor;
pub use tracker_data_block::*;
pub use vista_and_above_id_list_data_block::*;
type Result<T> = std::result::Result<T, ExtraDataError>;
#[derive(Clone, Debug, Default)]
pub struct ExtraData {
darwin_props: Option<DarwinDataBlock>,
special_folder_props: Option<SpecialFolderDataBlock>,
pub console_props: Option<ConsoleDataBlock>,
pub console_fe_props: Option<ConsoleFEDataBlock>,
environment_props: Option<EnvironmentVariableDataBlock>,
icon_environment_props: Option<IconEnvironmentDataBlock>,
known_folder_props: Option<KnownFolderDataBlock>,
property_store_props: Option<PropertyStoreDataBlock>,
pub shim_props: Option<ShimDataBlock>,
tracker_props: Option<TrackerDataBlock>,
vista_and_above_idlist_props: Option<VistaAndAboveIDListDataBlock>,
}
impl ExtraData {
pub fn new(cursor: &mut Cursor<Vec<u8>>, _header: &ShellLinkHeader) -> Result<Self> {
let mut this = Self::default();
while {
match this.parse_next_block(cursor) {
Err(ExtraDataError::UnknownBlock(a, b)) => Err(ExtraDataError::UnknownBlock(a, b)),
Err(_) => Ok(false),
Ok(_) => Ok(true),
}?
} {}
Ok(this)
}
fn parse_next_block(
&mut self,
cursor: &mut Cursor<Vec<u8>>,
) -> std::result::Result<(), ExtraDataError> {
let block_size = cursor.read_u32::<LE>().map_err(ExtraDataError::Read)?;
let block_signature = cursor.read_u32::<LE>().map_err(ExtraDataError::Read)?;
match (block_size, block_signature) {
(0x0000_0314, 0xa000_0001) => {
self.environment_props =
EnvironmentVariableDataBlock::new(block_size, block_signature, cursor)
.map(Some)?;
Ok(())
}
(0x0000_00cc, 0xa000_0002) => {
self.console_props =
ConsoleDataBlock::new(block_size, block_signature, cursor).map(Some)?;
Ok(())
}
(0x0000_0060, 0xa000_0003) => {
self.tracker_props =
TrackerDataBlock::new(block_size, block_signature, cursor).map(Some)?;
Ok(())
}
(0x0000_000c, 0xa000_0004) => {
self.console_fe_props =
ConsoleFEDataBlock::new(block_size, block_signature, cursor).map(Some)?;
Ok(())
}
(0x0000_0010, 0xa000_0005) => {
self.special_folder_props =
SpecialFolderDataBlock::new(block_size, block_signature, cursor).map(Some)?;
Ok(())
}
(0x0000_0314, 0xa000_0006) => {
self.darwin_props =
DarwinDataBlock::new(block_size, block_signature, cursor).map(Some)?;
Ok(())
}
(0x0000_0314, 0xa000_0007) => {
self.icon_environment_props =
IconEnvironmentDataBlock::new(block_size, block_signature, cursor).map(Some)?;
Ok(())
}
(_, 0xa000_0008) => {
self.shim_props =
ShimDataBlock::new(block_size, block_signature, cursor).map(Some)?;
Ok(())
}
(_, 0xa000_0009) => {
self.property_store_props =
PropertyStoreDataBlock::new(block_size, block_signature, cursor).map(Some)?;
Ok(())
}
(0x0000_001c, 0xa000_000b) => {
self.known_folder_props =
KnownFolderDataBlock::new(block_size, block_signature, cursor).map(Some)?;
Ok(())
}
(_, 0xa000_000c) => {
self.vista_and_above_idlist_props =
VistaAndAboveIDListDataBlock::new(block_size, block_signature, cursor)
.map(Some)?;
Ok(())
}
(size, signature) => Err(ExtraDataError::UnknownBlock(size, signature)),
}
}
}