use pelite;
use pelite::pe32::{Va, Ptr, Pe, PeFile};
use pelite::{util::CStr, Pod};
use pelite::pattern as pat;
pub fn print(client: PeFile, dll_name: &str) {
let classes = classes(client);
tprint! {
"### ClientClasses\n\n"
for cls in (&classes) {
"<details>\n"
"<summary><code>client_class "{cls.network_name}"</code></summary>\n\n"
"sizeof: `"{cls.size_of}"` \n"
"</details>\n"
}
"\n```\n"
for cls in (&classes) {
{dll_name}"!"{cls.address;#010x}" ClientClass "{cls.network_name}"\n"
}
"```\n\n"
}
}
#[allow(non_snake_case)]
#[derive(Pod, Debug)]
#[repr(C)]
struct ClientClass {
pCreateFn: Ptr,
pCreateEventFn: Ptr,
pNetworkName: Ptr<CStr>,
pRecvTable: Va,
pNext: Ptr<ClientClass>,
ClassID: i32,
}
#[derive(Debug)]
pub struct Class<'a> {
pub network_name: &'a str,
pub address: u32,
pub class_id: i32,
pub size_of: u32,
}
pub fn classes<'a>(client: PeFile<'a>) -> Vec<Class<'a>> {
let mut save = [0; 8];
let mut list = Vec::new();
let mut matches = client.scanner().matches_code(pat!("@4 A1*{'} A3*{'} C705*{'}*{'???? ???? *{'}} C3"));
while matches.next(&mut save) {
if save[1] != save[3] || save[2] != save[4] + 0x10 {
continue;
}
let address = save[4];
let client_class: &ClientClass = client.derva(address).unwrap();
let network_name = client.deref_c_str(client_class.pNetworkName).unwrap().to_str().unwrap();
let size_of = client.deref_copy::<u32>(client_class.pCreateFn.offset(39)).unwrap_or(0);
let class_id = 0;
list.push(Class { network_name, address, class_id, size_of })
}
list.sort_unstable_by_key(|cls| cls.network_name);
return list;
}