1use std::{fmt, iter, mem, result};
15
16use crate::{Error, Result};
17
18const DANS_MARKER: u32 = 0x536e6144; const RICH_MARKER: u32 = 0x68636952; #[derive(Copy, Clone)]
31pub struct RichStructure<'a> {
32 dos_stub: &'a [u32],
33 image: &'a [u32],
34}
35impl<'a> RichStructure<'a> {
36 pub(crate) fn try_from(image: &'a [u32]) -> Result<RichStructure<'a>> {
37 let image = image.get(15)
39 .and_then(|e_lfanew| image.get(..(e_lfanew / 4) as usize))
40 .ok_or(Error::Invalid)?;
41
42 let mut end = image.len();
44 loop {
45 if end < 16 {
46 return Err(Error::Invalid);
47 }
48 if image[end - 1] != 0 {
49 break;
50 }
51 end -= 1;
52 }
53 let end = end;
54
55 if image[end - 2] != RICH_MARKER {
57 return Err(Error::BadMagic);
58 }
59 let x = image[end - 1];
60 let dx = DANS_MARKER ^ x;
61
62 let mut start = end - 6;
64 loop {
65 if start < 16 {
66 return Err(Error::Invalid);
67 }
68 if image[start] == dx && image[start + 1] == x && image[start + 2] == x && image[start + 3] == x {
69 break;
70 }
71 start -= 2;
72 }
73 let start = start;
74
75 let dos_stub = &image[..start];
77 let image = &image[start..end];
78
79 Ok(RichStructure { dos_stub, image })
80 }
81 pub fn image(&self) -> &'a [u32] {
83 self.image
84 }
85 pub fn checksum(&self) -> u32 {
89 Self::_checksum(self.dos_stub, self.records())
90 }
91 fn _checksum<I>(dos_stub: &[u32], records: I) -> u32 where I: Iterator<Item = RichRecord> {
92 let mut csum = mem::size_of_val(dos_stub) as u32;
93
94 let mut i = 0;
95 for dword in dos_stub {
96 let bytes = if i == 0x3c { [0; 4] }
98 else { unsafe { *(dword as *const _ as *const [u8; 4]) } };
99 csum = u32::wrapping_add(csum, (bytes[0] as u32).rotate_left(i + 0));
101 csum = u32::wrapping_add(csum, (bytes[1] as u32).rotate_left(i + 1));
102 csum = u32::wrapping_add(csum, (bytes[2] as u32).rotate_left(i + 2));
103 csum = u32::wrapping_add(csum, (bytes[3] as u32).rotate_left(i + 3));
104 i += 4;
105 }
106
107 for record in records {
108 let value = (record.product as u32) << 16 | (record.build as u32);
109 csum = u32::wrapping_add(csum, value.rotate_left(record.count));
110 }
111
112 csum
113 }
114 pub fn xor_key(&self) -> u32 {
116 self.image[1]
117 }
118 pub fn records(&self) -> RichIter<'a> {
120 let iter = &self.image[4..self.image.len() - 2];
121 let key = self.xor_key();
122 RichIter { iter, key }
123 }
124 pub fn encode(&self, records: &[RichRecord], dest: &mut [u32]) -> result::Result<usize, usize> {
131 let xor_key = Self::_checksum(self.dos_stub, records.iter().cloned());
132 let n = records.len();
133 let total_size = ((xor_key / 32) % 3 + n as u32) * 8 + 0x20;
134 let total_len = (total_size / 4) as usize;
135 if dest.len() < n * 2 + 6 {
136 Err(total_len)
137 }
138 else {
139 dest[0] = DANS_MARKER ^ xor_key;
141 dest[1] = xor_key;
142 dest[2] = xor_key;
143 dest[3] = xor_key;
144 for (i, record) in records.iter().enumerate() {
146 let values = record.encode(xor_key);
147 dest[i * 2 + 4] = values[0];
148 dest[i * 2 + 5] = values[1];
149 }
150 dest[n * 2 + 4] = RICH_MARKER;
152 dest[n * 2 + 5] = xor_key;
153 for i in n * 2 + 6..dest.len() {
155 dest[i] = 0;
156 }
157 Ok(total_len)
158 }
159 }
160}
161impl<'a> fmt::Debug for RichStructure<'a> {
162 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
163 f.debug_struct("RichStructure")
164 .field("xor_key", &self.xor_key())
165 .field("checksum", &self.checksum())
166 .field("records", &self.records())
167 .finish()
168 }
169}
170
171#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
178#[repr(C)]
179pub struct RichRecord {
180 pub build: u16,
181 pub product: u16,
182 pub count: u32,
183}
184impl RichRecord {
185 pub fn decode(key: u32, values: &[u32; 2]) -> RichRecord {
187 let field = values[0] ^ key;
188 let build = (field & 0xffff) as u16;
189 let product = ((field >> 16) & 0xffff) as u16;
190 let count = values[1] ^ key;
191 RichRecord { build, product, count }
192 }
193 pub fn encode(&self, key: u32) -> [u32; 2] {
195 let value = (self.product as u32) << 16 | (self.build as u32);
196 [value ^ key, self.count ^ key]
197 }
198}
199
200#[derive(Copy, Clone, Debug, Eq, PartialEq)]
207#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
208pub enum ObjectKind {
209 Unknown,
210 Link,
211 Export,
213 Import,
215 Resource,
217 Assembly,
219 #[cfg_attr(feature = "serde", serde(rename = "C++"))]
221 CPP,
222 C,
224}
225impl From<u16> for ObjectKind {
226 fn from(product: u16) -> ObjectKind {
227 match product {
228 0x00ff | 0x00c9 | 0x009a | 0x007c | 0x005e | 0x0045 | 0x0006 => ObjectKind::Resource,
229 0x0100 | 0x00dc | 0x00ca | 0x009b | 0x0092 | 0x007a | 0x005c | 0x003f => ObjectKind::Export,
230 0x0101 | 0x00dd | 0x00cb | 0x009c | 0x0093 | 0x007b | 0x005d | 0x0019 | 0x0002 => ObjectKind::Import,
231 0x0102 | 0x00de | 0x00cc | 0x009d | 0x0091 | 0x0078 | 0x005a | 0x003d | 0x0004 => ObjectKind::Link,
232 0x0103 | 0x00df | 0x00cd | 0x009e | 0x0095 | 0x007d | 0x000f | 0x0040 => ObjectKind::Assembly,
233 0x0104 | 0x00e0 | 0x00ce | 0x00aa | 0x0083 | 0x006d | 0x005f | 0x001c | 0x000a | 0x0015 => ObjectKind::C,
234 0x0105 | 0x00e1 | 0x00cf | 0x00ab | 0x0084 | 0x006e | 0x0060 | 0x001d | 0x000b | 0x0016 => ObjectKind::CPP,
235
236 0x0001 => ObjectKind::Import,
237 _ => ObjectKind::Unknown,
238 }
239 }
240}
241
242#[derive(Clone)]
246pub struct RichIter<'a> {
247 iter: &'a [u32],
248 key: u32,
249}
250impl<'a> Iterator for RichIter<'a> {
251 type Item = RichRecord;
252 fn next(&mut self) -> Option<RichRecord> {
253 if self.iter.len() >= 2 {
254 let record = RichRecord::decode(self.key, &[self.iter[0], self.iter[1]]);
255 self.iter = &self.iter[2..];
256 Some(record)
257 }
258 else {
259 None
260 }
261 }
262 fn size_hint(&self) -> (usize, Option<usize>) {
263 let len = self.iter.len() / 2;
264 (len, Some(len))
265 }
266 fn count(self) -> usize {
267 self.size_hint().0
268 }
269 fn nth(&mut self, n: usize) -> Option<RichRecord> {
270 if self.iter.len() >= n * 2 + 2 {
271 let record = RichRecord::decode(self.key, &[self.iter[n * 2], self.iter[n * 2 + 1]]);
272 self.iter = &self.iter[n * 2 + 2..];
273 Some(record)
274 }
275 else {
276 self.iter = &self.iter[..0];
277 None
278 }
279 }
280}
281impl<'a> DoubleEndedIterator for RichIter<'a> {
282 fn next_back(&mut self) -> Option<RichRecord> {
283 let len = self.iter.len();
284 if len >= 2 {
285 let record = RichRecord::decode(self.key, &[self.iter[len - 2], self.iter[len - 1]]);
286 self.iter = &self.iter[..len - 2];
287 Some(record)
288 }
289 else {
290 None
291 }
292 }
293}
294impl<'a> ExactSizeIterator for RichIter<'a> {}
295impl<'a> iter::FusedIterator for RichIter<'a> {}
296impl<'a> fmt::Debug for RichIter<'a> {
297 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
298 f.debug_list().entries(self.clone()).finish()
299 }
300}
301
302#[cfg(feature = "serde")]
319mod serde {
320 use crate::util::serde_helper::*;
321 use super::{RichStructure, RichRecord};
322
323 impl<'a> Serialize for RichStructure<'a> {
324 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
325 let mut state = serializer.serialize_struct("RichStructure", 3)?;
326 state.serialize_field("xor_key", &self.xor_key())?;
327 state.serialize_field("checksum", &self.checksum())?;
328 state.serialize_field("records", &SerdeIter(self.records()))?;
329 state.end()
330 }
331 }
332 impl Serialize for RichRecord {
333 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
334 let mut state = serializer.serialize_struct("RichRecrod", 4)?;
335 state.serialize_field("product", &self.product)?;
336 state.serialize_field("build", &self.build)?;
338 state.serialize_field("count", &self.count)?;
339 state.end()
340 }
341 }
342}