(exports: &[DllExport], forward_target: &str)
| 16 | } |
| 17 | |
| 18 | fn generate_proxy_source(exports: &[DllExport], forward_target: &str) -> String { |
| 19 | let named: Vec<(usize, &str)> = exports |
| 20 | .iter() |
| 21 | .filter_map(|e| e.name.as_deref()) |
| 22 | .enumerate() |
| 23 | .collect(); |
| 24 | |
| 25 | let dll_filename = format!("{}.dll", forward_target); |
| 26 | let mut s = String::new(); |
| 27 | |
| 28 | s.push_str("use std::arch::naked_asm;\n"); |
| 29 | s.push_str("use std::sync::atomic::{AtomicUsize, Ordering};\n\n"); |
| 30 | |
| 31 | s.push_str("#[link(name = \"kernel32\")]\n"); |
| 32 | s.push_str("extern \"system\" {\n"); |
| 33 | s.push_str(" #[link_name = \"LoadLibraryA\"]\n"); |
| 34 | s.push_str(" fn rp_load_library(name: *const u8) -> isize;\n"); |
| 35 | s.push_str(" #[link_name = \"GetProcAddress\"]\n"); |
| 36 | s.push_str(" fn rp_get_proc_address(module: isize, name: *const u8) -> usize;\n"); |
| 37 | s.push_str("}\n\n"); |
| 38 | |
| 39 | for (i, name) in &named { |
| 40 | s.push_str(&format!( |
| 41 | "static RP_ADDR_{}: AtomicUsize = AtomicUsize::new(0); // {}\n", |
| 42 | i, name |
| 43 | )); |
| 44 | } |
| 45 | if !named.is_empty() { |
| 46 | s.push('\n'); |
| 47 | } |
| 48 | |
| 49 | s.push_str("pub unsafe fn init() {\n"); |
| 50 | s.push_str(&format!( |
| 51 | " let h = rp_load_library(b\"{}\\0\".as_ptr());\n", |
| 52 | dll_filename |
| 53 | )); |
| 54 | s.push_str(" if h == 0 { return; }\n"); |
| 55 | for (i, name) in &named { |
| 56 | s.push_str(&format!( |
| 57 | " RP_ADDR_{}.store(rp_get_proc_address(h, b\"{}\\0\".as_ptr()), Ordering::Release);\n", |
| 58 | i, name |
| 59 | )); |
| 60 | } |
| 61 | s.push_str("}\n\n"); |
| 62 | |
| 63 | for (i, name) in &named { |
| 64 | s.push_str("#[unsafe(naked)]\n"); |
| 65 | s.push_str(&format!("#[export_name = \"{}\"]\n", name)); |
| 66 | s.push_str(&format!( |
| 67 | "pub unsafe extern \"system\" fn _rp_fwd_{}() {{\n", |
| 68 | i |
| 69 | )); |
| 70 | s.push_str(&format!( |
| 71 | " naked_asm!(\"jmp qword ptr [rip + {{addr}}]\", addr = sym RP_ADDR_{});\n", |
| 72 | i |
| 73 | )); |
| 74 | s.push_str("}\n\n"); |
| 75 | } |
no outgoing calls