pelite\wrap/
exports.rs

1use crate::*;
2use super::Wrap;
3use super::imports::Import;
4
5/// Exported symbol.
6#[derive(Copy, Clone, Debug, Eq, PartialEq)]
7#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
8pub enum Export<'a> {
9	/// Standard exported symbol.
10	Symbol(&'a u32),
11	/// This export is forwarded to another dll.
12	///
13	/// Format of the string is `"DllName.ExportName"`.
14	/// For more information see this [blog post](https://blogs.msdn.microsoft.com/oldnewthing/20060719-24/?p=30473) by Raymond Chen.
15	Forward(&'a util::CStr),
16}
17impl<'a> Export<'a> {
18	/// Returns some if the symbol is exported.
19	#[inline]
20	pub fn symbol(self) -> Option<u32> {
21		match self {
22			Export::Symbol(&rva) => Some(rva),
23			_ => None,
24		}
25	}
26	/// Returns some if the symbol is forwarded.
27	#[inline]
28	pub fn forward(self) -> Option<&'a util::CStr> {
29		match self {
30			Export::Forward(name) => Some(name),
31			_ => None,
32		}
33	}
34}
35
36/// Export directory.
37impl<'a, Pe32: pe32::Pe<'a>, Pe64: pe64::Pe<'a>> Wrap<pe32::exports::Exports<'a, Pe32>, pe64::exports::Exports<'a, Pe64>> {
38	/// Gets the PE instance.
39	#[inline]
40	pub fn pe(&self) -> Wrap<Pe32, Pe64> {
41		match self {
42			Wrap::T32(exports) => Wrap::T32(exports.pe()),
43			Wrap::T64(exports) => Wrap::T64(exports.pe()),
44		}
45	}
46	/// Returns the underlying export directory image.
47	#[inline]
48	pub fn image(&self) -> &'a image::IMAGE_EXPORT_DIRECTORY {
49		match self {
50			Wrap::T32(exports) => exports.image(),
51			Wrap::T64(exports) => exports.image(),
52		}
53	}
54	/// Gets the export directory's name for this library.
55	#[inline]
56	pub fn dll_name(&self) -> Result<&'a util::CStr> {
57		match self {
58			Wrap::T32(exports) => exports.dll_name(),
59			Wrap::T64(exports) => exports.dll_name(),
60		}
61	}
62	/// Gets the ordinal base for the exported functions.
63	#[inline]
64	pub fn ordinal_base(&self) -> u16 {
65		match self {
66			Wrap::T32(exports) => exports.ordinal_base(),
67			Wrap::T64(exports) => exports.ordinal_base(),
68		}
69	}
70	/// Gets the export address table.
71	#[inline]
72	pub fn functions(&self) -> Result<&'a [u32]> {
73		match self {
74			Wrap::T32(exports) => exports.functions(),
75			Wrap::T64(exports) => exports.functions(),
76		}
77	}
78	/// Gets the name address table.
79	#[inline]
80	pub fn names(&self) -> Result<&'a [u32]> {
81		match self {
82			Wrap::T32(exports) => exports.names(),
83			Wrap::T64(exports) => exports.names(),
84		}
85	}
86	/// Gets the name index table.
87	#[inline]
88	pub fn name_indices(&self) -> Result<&'a [u16]> {
89		match self {
90			Wrap::T32(exports) => exports.name_indices(),
91			Wrap::T64(exports) => exports.name_indices(),
92		}
93	}
94	/// Query the exports.
95	#[inline]
96	pub fn by(&self) -> Result<Wrap<pe32::exports::By<'a, Pe32>, pe64::exports::By<'a, Pe64>>> {
97		match self {
98			Wrap::T32(exports) => Wrap::T32(exports.by()).transpose(),
99			Wrap::T64(exports) => Wrap::T64(exports.by()).transpose(),
100		}
101	}
102}
103
104/// Export directory symbol lookup.
105impl<'a, Pe32: pe32::Pe<'a>, Pe64: pe64::Pe<'a>> Wrap<pe32::exports::By<'a, Pe32>, pe64::exports::By<'a, Pe64>> {
106	/// Gets the PE instance.
107	#[inline]
108	pub fn pe(&self) -> Wrap<Pe32, Pe64> {
109		match self {
110			Wrap::T32(by) => Wrap::T32(by.pe()),
111			Wrap::T64(by) => Wrap::T64(by.pe()),
112		}
113	}
114	/// Returns the underlying export directory image.
115	#[inline]
116	pub fn image(&self) -> &'a image::IMAGE_EXPORT_DIRECTORY {
117		match self {
118			Wrap::T32(by) => by.image(),
119			Wrap::T64(by) => by.image(),
120		}
121	}
122	/// Gets the export directory's name for this library.
123	#[inline]
124	pub fn dll_name(&self) -> Result<&'a util::CStr> {
125		match self {
126			Wrap::T32(by) => by.dll_name(),
127			Wrap::T64(by) => by.dll_name(),
128		}
129	}
130	/// Gets the ordinal base for the exported functions.
131	#[inline]
132	pub fn ordinal_base(&self) -> u16 {
133		match self {
134			Wrap::T32(by) => by.ordinal_base(),
135			Wrap::T64(by) => by.ordinal_base(),
136		}
137	}
138	/// Gets the export address table.
139	#[inline]
140	pub fn functions(&self) -> &'a [u32] {
141		match self {
142			Wrap::T32(by) => by.functions(),
143			Wrap::T64(by) => by.functions(),
144		}
145	}
146	/// Gets the name address table.
147	#[inline]
148	pub fn names(&self) -> &'a [u32] {
149		match self {
150			Wrap::T32(by) => by.names(),
151			Wrap::T64(by) => by.names(),
152		}
153	}
154	/// Gets the name index table.
155	#[inline]
156	pub fn name_indices(&self) -> &'a [u16] {
157		match self {
158			Wrap::T32(by) => by.name_indices(),
159			Wrap::T64(by) => by.name_indices(),
160		}
161	}
162	/// Validates and checks if the name table is sorted.
163	#[inline]
164	pub fn check_sorted(&self) -> Result<bool> {
165		match self {
166			Wrap::T32(by) => by.check_sorted(),
167			Wrap::T64(by) => by.check_sorted(),
168		}
169	}
170	/// Looks up an `Export` by its ordinal.
171	#[inline]
172	pub fn ordinal(&self, ordinal: u16) -> Result<Export<'a>> {
173		match self {
174			Wrap::T32(by) => by.ordinal(ordinal),
175			Wrap::T64(by) => by.ordinal(ordinal),
176		}
177	}
178	/// Looks up an `Export` by its name.
179	#[inline]
180	pub fn name_linear<S: AsRef<[u8]> + ?Sized>(&self, name: &S) -> Result<Export<'a>> {
181		match self {
182			Wrap::T32(by) => by.name_linear(name),
183			Wrap::T64(by) => by.name_linear(name),
184		}
185	}
186	/// Looks up an `Export` by its name.
187	#[inline]
188	pub fn name<S: AsRef<[u8]> + ?Sized>(&self, name: &S) -> Result<Export<'a>> {
189		match self {
190			Wrap::T32(by) => by.name(name),
191			Wrap::T64(by) => by.name(name),
192		}
193	}
194	/// Looks up an `Export` by its import.
195	#[inline]
196	pub fn import(&self, import: Import) -> Result<Export<'a>> {
197		match self {
198			Wrap::T32(by) => by.import(import),
199			Wrap::T64(by) => by.import(import),
200		}
201	}
202	/// Looks up an export by its index.
203	#[inline]
204	pub fn index(&self, index: usize) -> Result<Export<'a>> {
205		match self {
206			Wrap::T32(by) => by.index(index),
207			Wrap::T64(by) => by.index(index),
208		}
209	}
210	/// Looks up an export by its hint.
211	#[inline]
212	pub fn hint(&self, hint: usize) -> Result<Export<'a>> {
213		match self {
214			Wrap::T32(by) => by.hint(hint),
215			Wrap::T64(by) => by.hint(hint),
216		}
217	}
218	/// Looks up an export by its hint and falls back to the name if the hint is incorrect.
219	#[inline]
220	pub fn hint_name<S: AsRef<[u8]> + ?Sized>(&self, hint: usize, name: &S) -> Result<Export<'a>> {
221		match self {
222			Wrap::T32(by) => by.hint_name(hint, name),
223			Wrap::T64(by) => by.hint_name(hint, name),
224		}
225	}
226	/// Looks up the name for a hint.
227	#[inline]
228	pub fn name_of_hint(&self, hint: usize) -> Result<&'a util::CStr> {
229		match self {
230			Wrap::T32(by) => by.name_of_hint(hint),
231			Wrap::T64(by) => by.name_of_hint(hint),
232		}
233	}
234	/// Given an index in the functions array, gets the named export.
235	#[inline]
236	pub fn name_lookup(&self, index: usize) -> Result<Import<'a>> {
237		match self {
238			Wrap::T32(by) => by.name_lookup(index),
239			Wrap::T64(by) => by.name_lookup(index),
240		}
241	}
242	#[inline]
243	fn symbol_from_rva(&self, rva: &'a u32) -> Result<Export<'a>> {
244		match self {
245			Wrap::T32(by) => by.symbol_from_rva(rva),
246			Wrap::T64(by) => by.symbol_from_rva(rva),
247		}
248	}
249	/// Iterate over exported functions.
250	#[inline]
251	pub fn iter<'s>(&'s self) -> impl 's + Clone + Iterator<Item = Result<Export<'a>>> {
252		self.functions().iter().map(move |rva| self.symbol_from_rva(rva))
253	}
254	/// Iterate over functions exported by name.
255	#[inline]
256	pub fn iter_names<'s>(&'s self) -> impl 's + Clone + Iterator<Item = (Result<&'a util::CStr>, Result<Export<'a>>)> {
257		(0..self.names().len() as u32)
258			.map(move |hint| (
259				self.name_of_hint(hint as usize),
260				self.hint(hint as usize),
261			))
262	}
263	/// Iterate over functions exported by name, returning their name and index in the functions table.
264	#[inline]
265	pub fn iter_name_indices<'s>(&'s self) -> impl 's + Clone + Iterator<Item = (Result<&'a util::CStr>, usize)> {
266		(0..self.names().len() as u32)
267			.map(move |hint| (
268				self.name_of_hint(hint as usize),
269				self.name_indices()[hint as usize] as usize,
270			))
271	}
272}
273
274/// Convenient way to get an exported address.
275impl<'a, Pe32: pe32::Pe<'a>, Pe64: pe64::Pe<'a>> Wrap<Pe32, Pe64> {
276	/// Convenient method to get an exported function by ordinal.
277	#[inline]
278	pub fn get_export_by_ordinal(&self, ordinal: u16) -> Result<Export<'a>> {
279		use pe32::exports::GetProcAddress as _;
280		use pe64::exports::GetProcAddress as _;
281		match self {
282			Wrap::T32(pe32) => pe32.get_export(ordinal),
283			Wrap::T64(pe64) => pe64.get_export(ordinal),
284		}
285	}
286	/// Convenient method to get an exported function by import.
287	#[inline]
288	pub fn get_export_by_import(&self, import: Import<'a>) -> Result<Export<'a>> {
289		use pe32::exports::GetProcAddress as _;
290		use pe64::exports::GetProcAddress as _;
291		match self {
292			Wrap::T32(pe32) => pe32.get_export(import),
293			Wrap::T64(pe64) => pe64.get_export(import),
294		}
295	}
296	/// Convenient method to get an exported function by name.
297	#[inline]
298	pub fn get_export_by_name<S: ?Sized + AsRef<[u8]>>(&self, name: &S) -> Result<Export<'a>> {
299		use pe32::exports::GetProcAddress as _;
300		use pe64::exports::GetProcAddress as _;
301		match self {
302			Wrap::T32(pe32) => pe32.get_export(name),
303			Wrap::T64(pe64) => pe64.get_export(name),
304		}
305	}
306}