1use alloc::string::{String, ToString};
6use core::{mem, slice};
7
8use zerocopy::{FromBytes, Immutable, IntoBytes};
9
10#[repr(C, packed(1))]
11#[derive(
12 Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, IntoBytes, Immutable, Default,
13)]
14pub struct VersionU8 {
15 pub major: u8,
16 pub minor: u8,
17}
18#[repr(C, packed(2))]
19#[derive(
20 Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, IntoBytes, Immutable, Default,
21)]
22pub struct VersionU16 {
23 pub major: u16,
24 pub minor: u16,
25}
26#[repr(C, packed(4))]
27#[derive(
28 Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, IntoBytes, Immutable, Default,
29)]
30pub struct VersionU32 {
31 pub major: u32,
32 pub minor: u32,
33}
34#[repr(C, packed(2))]
35#[derive(
36 Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, IntoBytes, Immutable, Default,
37)]
38pub struct CoffHeader {
39 pub machine: u16,
40 pub number_of_sections: u16,
41 pub time_date_stamp: u32,
42 pub pointer_to_symbol_table: u32,
43 pub number_of_symbols: u32,
44 pub size_of_optional_header: u16,
45 pub characteristics: u16,
46}
47#[repr(C, packed(2))]
48#[derive(
49 Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, IntoBytes, Immutable, Default,
50)]
51pub struct StandardHeader {
52 pub magic: u16,
53 pub linker_version: VersionU8,
54 pub size_of_code: u32,
55 pub size_of_initialized_data: u32,
56 pub size_of_uninitialized_data: u32,
57 pub address_of_entry_point: u32,
58 pub base_of_code: u32,
59}
60#[repr(C)]
61#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, Default)]
62pub struct WindowsHeader<UXX> {
63 pub image_base: UXX,
64 pub section_alignment: u32,
65 pub file_alignment: u32,
66 pub operating_system_version: VersionU16,
67 pub image_version: VersionU16,
68 pub subsystem_version: VersionU16,
69 pub win32_version_value: u32,
70 pub size_of_image: u32,
71 pub size_of_headers: u32,
72 pub check_sum: u32,
73 pub subsystem: u16,
74 pub dll_characteristics: u16,
75 pub size_of_stack_reserve: UXX,
76 pub size_of_stack_commit: UXX,
77 pub size_of_heap_reserve: UXX,
78 pub size_of_heap_commit: UXX,
79 pub loader_flags: u32,
80 pub number_of_rva_and_sizes: u32,
81}
82impl<UXX> WindowsHeader<UXX>
83where
84 UXX: IntoBytes,
85{
86 pub fn as_bytes(&self) -> &[u8] {
87 unsafe {
89 let len = mem::size_of_val(self);
90 slice::from_raw_parts(self as *const Self as *const u8, len)
91 }
92 }
93}
94
95#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
96pub enum GenericWindowsHeader {
97 WindowsHeader32(WindowsHeader<u32>),
98 WindowsHeader64(WindowsHeader<u64>),
99}
100impl GenericWindowsHeader {
101 pub fn as_bytes(&self) -> &[u8] {
102 match self {
103 GenericWindowsHeader::WindowsHeader32(header) => header.as_bytes(),
104 GenericWindowsHeader::WindowsHeader64(header) => header.as_bytes(),
105 }
106 }
107
108 pub const fn section_alignment(&self) -> u32 {
109 match self {
110 GenericWindowsHeader::WindowsHeader32(header) => header.section_alignment,
111 GenericWindowsHeader::WindowsHeader64(header) => header.section_alignment,
112 }
113 }
114
115 pub const fn file_alignment(&self) -> u32 {
116 match self {
117 GenericWindowsHeader::WindowsHeader32(header) => header.file_alignment,
118 GenericWindowsHeader::WindowsHeader64(header) => header.file_alignment,
119 }
120 }
121
122 pub const fn operating_system_version(&self) -> VersionU16 {
123 match self {
124 GenericWindowsHeader::WindowsHeader32(header) => header.operating_system_version,
125 GenericWindowsHeader::WindowsHeader64(header) => header.operating_system_version,
126 }
127 }
128
129 pub const fn image_version(&self) -> VersionU16 {
130 match self {
131 GenericWindowsHeader::WindowsHeader32(header) => header.image_version,
132 GenericWindowsHeader::WindowsHeader64(header) => header.image_version,
133 }
134 }
135
136 pub const fn subsystem_version(&self) -> VersionU16 {
137 match self {
138 GenericWindowsHeader::WindowsHeader32(header) => header.subsystem_version,
139 GenericWindowsHeader::WindowsHeader64(header) => header.subsystem_version,
140 }
141 }
142
143 pub const fn win32_version_value(&self) -> u32 {
144 match self {
145 GenericWindowsHeader::WindowsHeader32(header) => header.win32_version_value,
146 GenericWindowsHeader::WindowsHeader64(header) => header.win32_version_value,
147 }
148 }
149
150 pub const fn size_of_image(&self) -> u32 {
151 match self {
152 GenericWindowsHeader::WindowsHeader32(header) => header.size_of_image,
153 GenericWindowsHeader::WindowsHeader64(header) => header.size_of_image,
154 }
155 }
156
157 pub const fn size_of_headers(&self) -> u32 {
158 match self {
159 GenericWindowsHeader::WindowsHeader32(header) => header.size_of_headers,
160 GenericWindowsHeader::WindowsHeader64(header) => header.size_of_headers,
161 }
162 }
163
164 pub const fn check_sum(&self) -> u32 {
165 match self {
166 GenericWindowsHeader::WindowsHeader32(header) => header.check_sum,
167 GenericWindowsHeader::WindowsHeader64(header) => header.check_sum,
168 }
169 }
170
171 pub const fn subsystem(&self) -> u16 {
172 match self {
173 GenericWindowsHeader::WindowsHeader32(header) => header.subsystem,
174 GenericWindowsHeader::WindowsHeader64(header) => header.subsystem,
175 }
176 }
177
178 pub const fn dll_characteristics(&self) -> u16 {
179 match self {
180 GenericWindowsHeader::WindowsHeader32(header) => header.dll_characteristics,
181 GenericWindowsHeader::WindowsHeader64(header) => header.dll_characteristics,
182 }
183 }
184
185 pub const fn loader_flags(&self) -> u32 {
186 match self {
187 GenericWindowsHeader::WindowsHeader32(header) => header.loader_flags,
188 GenericWindowsHeader::WindowsHeader64(header) => header.loader_flags,
189 }
190 }
191
192 pub const fn number_of_rva_and_sizes(&self) -> u32 {
193 match self {
194 GenericWindowsHeader::WindowsHeader32(header) => header.number_of_rva_and_sizes,
195 GenericWindowsHeader::WindowsHeader64(header) => header.number_of_rva_and_sizes,
196 }
197 }
198}
199
200#[repr(C, packed(4))]
201#[derive(
202 Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, IntoBytes, Immutable, Default,
203)]
204pub struct ImageDataDirectory {
205 pub virtual_address: u32,
206 pub size: u32,
207}
208
209#[repr(C, packed(4))]
210#[derive(
211 Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, IntoBytes, Immutable, Default,
212)]
213pub struct SectionHeader {
214 pub name: u64,
215 pub virtual_size: u32,
216 pub virtual_address: u32,
217 pub size_of_raw_data: u32,
218 pub pointer_to_raw_data: u32,
219 pub pointer_to_relocations: u32,
220 pub pointer_to_linenumbers: u32,
221 pub number_of_relocations: u16,
222 pub number_of_linenumbers: u16,
223 pub characteristics: u32,
224}
225
226impl SectionHeader {
227 pub fn name(&self) -> Option<String> {
228 let name = self.name.to_le_bytes();
229 let name = core::str::from_utf8(
230 &name[0..name.iter().position(|&c| c == b'\0').unwrap_or(name.len())],
231 )
232 .ok();
233 name.map(|name| name.to_string())
234 }
235}
236
237#[repr(C, packed(2))]
238#[derive(
239 Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, IntoBytes, Immutable, Default,
240)]
241pub struct ResourceDirectoryTable {
242 pub characteristics: u32,
243 pub time_date_stamp: u32,
244 pub version: VersionU16,
245 pub number_of_name_entries: u16,
246 pub number_of_id_entries: u16,
247}
248
249#[repr(C, packed(4))]
250#[derive(
251 Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, IntoBytes, Immutable, Default,
252)]
253pub struct ResourceDirectoryEntry {
254 pub name_offset_or_integer_id: u32,
255 pub data_entry_or_subdirectory_offset: u32,
256}
257
258#[repr(C, packed(4))]
259#[derive(
260 Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, IntoBytes, Immutable, Default,
261)]
262pub struct ResourceDataEntry {
263 pub data_rva: u32,
264 pub size: u32,
265 pub codepage: u32,
266 pub reserved: u32,
267}
268
269#[repr(C, packed(2))]
270#[derive(
271 Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, IntoBytes, Immutable, Default,
272)]
273pub struct IconDirectory {
274 pub reserved: u16,
275 pub type_: u16,
276 pub count: u16,
277}
278
279#[repr(C, packed(1))]
280#[derive(
281 Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, IntoBytes, Immutable, Default,
282)]
283pub struct IconDirectoryEntry {
284 pub width: u8,
285 pub height: u8,
286 pub color_count: u8,
287 pub reserved: u8,
288 pub planes: u16,
289 pub bit_count: u16,
290 pub bytes: u32,
291 pub id: u16,
292}
293
294#[repr(C, packed(4))]
295#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, IntoBytes, Immutable)]
296pub struct FixedFileInfo {
297 pub signature: u32,
298 pub struct_version: VersionU16,
299 pub file_version: VersionU32,
300 pub product_version: VersionU32,
301 pub file_flags_mask: u32,
302 pub file_flags: u32,
303 pub file_os: u32,
304 pub file_type: u32,
305 pub file_subtype: u32,
306 pub file_date: u64,
307}
308impl Default for FixedFileInfo {
309 fn default() -> Self {
310 Self {
311 signature: 0xfeef04bd,
312 struct_version: VersionU16 { major: 0, minor: 1 },
313 file_version: VersionU32 { major: 1, minor: 0 },
314 product_version: VersionU32 { major: 1, minor: 0 },
315 file_flags_mask: 0x0000003f,
316 file_flags: 0x00000000,
317 file_os: 0x00040004,
318 file_type: 0x00000001,
319 file_subtype: 0x00000000,
320 file_date: 0x00000000,
321 }
322 }
323}
324
325#[repr(C, packed(2))]
326#[derive(
327 Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, FromBytes, IntoBytes, Immutable, Default,
328)]
329pub struct VersionHeader {
330 pub length: u16,
331 pub value_length: u16,
332 pub type_: u16,
333}