package oui
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
A tool that builds standalone installers for your OCaml applications
Install
dune-project
Dependency
Authors
Maintainers
Sources
oui-0.1.0.tbz
sha256=b806a63c9acd581a00729a48f1faf86b294cc82936fc705fc628a20ede33f977
sha512=e61c35a6e08671634c1edabd7b0add926ac6e0c6c43c9e0a095e89efab7696b6ae5cc1ea0844283a80640c19adb36478bdfb2414bbcab5077ceb7fd16ae45e66
doc/src/oui.lib/win_ldd.ml.html
Source file win_ldd.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230(**************************************************************************) (* *) (* Copyright 2023 OCamlPro *) (* *) (* All rights reserved. This file is distributed under the terms of the *) (* GNU Lesser General Public License version 2.1, with the special *) (* exception on linking described in the file LICENSE. *) (* *) (**************************************************************************) module StrSet = Set.Make (String) type reason = MZSize | MZSig | PESize | PESig | PEOptSize | PEOptSig exception Exit exception InvalidHeader of reason (* Size of various structures *) let mz_header_size = 0x40 let pe_header_size = 0x18 let pe32_header_size = 0x60 let pe32_plus_header_size = 0x70 let section_header_size = 0x28 let import_descriptor_size = 0x14 (* Header signatures *) let mz_magic = 0x4D5A (* "MZ" *) let pe_magic = 0x50450000l (* "PE\0\0" *) let pe32_magic = 0x0B01 let pe32_plus_magic = 0x0B02 (* MZ Header field offsets *) let mz_lfanew = 0x3C (* PE Header field offsets *) let pe_number_of_sections = 0x06 let pe_size_of_optional_header = 0x14 (* PE32(+) Optional Header field offsets *) let pe32_number_of_rva_and_sizes = 0x5C let pe32_plus_number_of_rva_and_sizes = 0x6C (* Data Directory field offsets *) let dd_imports_rva = 0x08 (* Import Descriptor field offsets *) let id_name = 0x0C let read_string = let buf = Buffer.create 64 in fun ic -> let rec aux () = match input_char ic with | '\000' -> Buffer.contents buf | c -> Buffer.add_char buf c; aux () in Buffer.reset buf; aux () let rva_to_address sect_hdr rva = let sh_opt = List.find_opt (fun (vs, va, _ds, _da) -> rva >= va && rva < va + vs ) sect_hdr in match sh_opt with | Some (_vs, va, _ds, da) -> da + (rva - va) | None -> 0 let get_dlls_ic ic = let mz_header = Bytes.create mz_header_size in begin try really_input ic mz_header 0 mz_header_size with End_of_file -> raise (InvalidHeader MZSize) end; let mz_sig = Bytes.get_uint16_be mz_header 0 in if mz_sig <> mz_magic then raise (InvalidHeader MZSig); let pe_address = Bytes.get_int32_le mz_header mz_lfanew |> Int32.to_int in seek_in ic pe_address; let pe_header = Bytes.create pe_header_size in begin try really_input ic pe_header 0 pe_header_size with End_of_file -> raise (InvalidHeader PESize) end; let pe_sig = Bytes.get_int32_be pe_header 0 in if pe_sig <> pe_magic then raise (InvalidHeader PESig); let nb_sections = Bytes.get_uint16_le pe_header pe_number_of_sections in let size_opt_hdr = Bytes.get_uint16_le pe_header pe_size_of_optional_header in if size_opt_hdr = 0 then raise Exit; seek_in ic (pe_address + pe_header_size); let pe_opt_header = Bytes.create size_opt_hdr in begin try really_input ic pe_opt_header 0 size_opt_hdr with End_of_file -> raise (InvalidHeader PEOptSize) end; let pe32_sig = Bytes.get_uint16_be pe_opt_header 0 in let nb_rva_sizes_offset, data_dir_offset = if pe32_sig = pe32_magic then pe32_number_of_rva_and_sizes, pe32_header_size else if pe32_sig = pe32_plus_magic then pe32_plus_number_of_rva_and_sizes, pe32_plus_header_size else raise (InvalidHeader PEOptSig); in let nb_rva_sizes = Bytes.get_int32_le pe_opt_header nb_rva_sizes_offset |> Int32.to_int in if nb_rva_sizes < 2 then raise Exit; let imports_rva = Bytes.get_int32_le pe_opt_header (data_dir_offset + dd_imports_rva) |> Int32.to_int in seek_in ic (pe_address + pe_header_size + size_opt_hdr); let sh = Bytes.create section_header_size in let rec aux i sect_hdrs = if i >= nb_sections then List.rev sect_hdrs else begin really_input ic sh 0 section_header_size; let virt_size = Bytes.get_int32_le sh 8 |> Int32.to_int in let virt_address = Bytes.get_int32_le sh 12 |> Int32.to_int in let data_size = Bytes.get_int32_le sh 16 |> Int32.to_int in let data_address = Bytes.get_int32_le sh 20 |> Int32.to_int in let sect_hdrs = (virt_size, virt_address, data_size, data_address) :: sect_hdrs in aux (i + 1) sect_hdrs end in let sect_hdrs = aux 0 [] in let imports_address = rva_to_address sect_hdrs imports_rva in let id = Bytes.create import_descriptor_size in let rec aux i names = seek_in ic (imports_address + i * import_descriptor_size); really_input ic id 0 import_descriptor_size; let name_rva = Bytes.get_int32_le id id_name |> Int32.to_int in if name_rva = 0 then names else let name_address = rva_to_address sect_hdrs name_rva in seek_in ic name_address; (* Note: the name is encoded using the current Windows ANSI encoding, not UTF-8 *) let name = read_string ic in aux (i + 1) (name :: names) in let names = aux 0 [] in names let get_dlls_t binary = let ic = open_in_bin binary in let dlls = try get_dlls_ic ic with | Exit | InvalidHeader _ -> [] | e -> close_in ic; raise e in close_in ic; dlls external get_windows_directory : unit -> string = "ml_get_windows_directory" let is_system32 = (* Note: guaranteed to end with '\' *) let win_dir = get_windows_directory () in fun path -> let prefix = try String.sub path 0 (String.length win_dir) with _ -> "" in if prefix <> win_dir then false else let suffix = try String.sub path (String.length win_dir) (String.length path - String.length win_dir) with _ -> "" in match String.split_on_char '\\' suffix with | directory :: _ -> String.lowercase_ascii directory = "system32" || String.lowercase_ascii directory = "syswow64" | _ -> false (* Note: string is encoded using the current Windows ANSI encoding, not UTF-8 *) external resolve_dll : string -> string option = "ml_resolve_dll" let get_dlls binary = let rec aux dlls binary = let binary_dlls = get_dlls_t binary in let new_dlls = List.filter_map (fun dll -> match resolve_dll dll with | None -> None (* Maybe should warn ? *) | Some (dll) -> if is_system32 dll then None else if StrSet.mem dll dlls then None else Some (dll) ) binary_dlls in let dlls = List.fold_left (fun dlls dll -> StrSet.add dll dlls ) dlls new_dlls in List.fold_left aux dlls new_dlls in let dlls = aux StrSet.empty (OpamFilename.to_string binary) in StrSet.fold (fun dll dlls -> OpamFilename.of_string (System.normalize_path dll) :: dlls ) dlls [] |> List.rev
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>