3 * Copyright (C) 2009-2011 Red Hat Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 (* This script generates language bindings and some documentation for
23 * After editing this file, run it (./generator/generator.ml) to
24 * regenerate all the output files. 'make' will rerun this
25 * automatically when necessary. Note that if you are using a separate
26 * build directory you must run generator.ml from the _source_
29 * IMPORTANT: This script should NOT print any warnings. If it prints
30 * warnings, you should treat them as errors.
32 * OCaml tips: (1) In emacs, install tuareg-mode to display and format
33 * OCaml code correctly. 'vim' comes with a good OCaml editing mode by
34 * default. (2) Read the resources at http://ocaml-tutorial.org/
43 type style = ret * args
45 | RErr (* 0 = ok, -1 = error *)
46 | RErrDispose (* Disposes handle, see hivex_close. *)
47 | RHive (* Returns a hive_h or NULL. *)
48 | RSize (* Returns size_t or 0. *)
49 | RNode (* Returns hive_node_h or 0. *)
50 | RNodeNotFound (* See hivex_node_get_child. *)
51 | RNodeList (* Returns hive_node_h* or NULL. *)
52 | RValue (* Returns hive_value_h or 0. *)
53 | RValueList (* Returns hive_value_h* or NULL. *)
54 | RString (* Returns char* or NULL. *)
55 | RStringList (* Returns char** or NULL. *)
56 | RLenType (* See hivex_value_type. *)
57 | RLenTypeVal (* See hivex_value_value. *)
58 | RInt32 (* Returns int32. *)
59 | RInt64 (* Returns int64. *)
61 and args = argt list (* List of parameters. *)
63 and argt = (* Note, cannot be NULL/0 unless it
64 says so explicitly below. *)
66 | ANode of string (* hive_node_h *)
67 | AValue of string (* hive_value_h *)
68 | AString of string (* char* *)
69 | AStringNullable of string (* char* (can be NULL) *)
70 | AOpenFlags (* HIVEX_OPEN_* flags list. *)
71 | AUnusedFlags (* Flags arg that is always 0 *)
72 | ASetValues (* See hivex_node_set_values. *)
73 | ASetValue (* See hivex_node_set_value. *)
76 * https://secure.wikimedia.org/wikipedia/en/wiki/Windows_Registry#Keys_and_values
78 * It's unfortunate that in our original C binding we strayed away from
79 * the names that Windows uses (eg. REG_SZ for strings). We include
80 * both our names and the Windows names.
84 "Just a key without a value";
86 "A Windows string (encoding is unknown, but often UTF16-LE)";
87 2, "expand_string", "EXPAND_SZ",
88 "A Windows string that contains %env% (environment variable expansion)";
89 3, "binary", "BINARY",
92 "DWORD (32 bit integer), little endian";
93 5, "dword_be", "DWORD_BIG_ENDIAN",
94 "DWORD (32 bit integer), big endian";
96 "Symbolic link to another part of the registry tree";
97 7, "multiple_strings", "MULTI_SZ",
98 "Multiple Windows strings. See http://blogs.msdn.com/oldnewthing/archive/2009/10/08/9904646.aspx";
99 8, "resource_list", "RESOURCE_LIST",
101 9, "full_resource_description", "FULL_RESOURCE_DESCRIPTOR",
102 "Resource descriptor";
103 10, "resource_requirements_list", "RESOURCE_REQUIREMENTS_LIST",
104 "Resouce requirements list";
105 11, "qword", "QWORD",
106 "QWORD (64 bit integer), unspecified endianness but usually little endian"
108 let max_hive_type = 11
110 (* Open flags (bitmask passed to AOpenFlags) *)
112 1, "VERBOSE", "Verbose messages";
113 2, "DEBUG", "Debug messages";
114 4, "WRITE", "Enable writes to the hive";
119 "open", (RHive, [AString "filename"; AOpenFlags]),
122 Opens the hive named C<filename> for reading.
124 Flags is an ORed list of the open flags (or C<0> if you don't
125 want to pass any flags). These flags are defined:
129 =item HIVEX_OPEN_VERBOSE
133 =item HIVEX_OPEN_DEBUG
135 Very verbose messages, suitable for debugging problems in the library
138 This is also selected if the C<HIVEX_DEBUG> environment variable
141 =item HIVEX_OPEN_WRITE
143 Open the hive for writing. If omitted, the hive is read-only.
145 See L<hivex(3)/WRITING TO HIVE FILES>.
149 "close", (RErrDispose, [AHive]),
150 "close a hive handle",
152 Close a hive handle and free all associated resources.
154 Note that any uncommitted writes are I<not> committed by this call,
155 but instead are lost. See L<hivex(3)/WRITING TO HIVE FILES>.";
157 "root", (RNode, [AHive]),
158 "return the root node of the hive",
160 Return root node of the hive. All valid hives must contain a root node.";
162 "last_modified", (RInt64, [AHive]),
163 "return the modification time from the header of the hive",
165 Return the modification time from the header of the hive.
167 The returned value is a Windows filetime.
168 To convert this to a Unix C<time_t> see:
169 L<http://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux/6161842#6161842>";
171 "node_name", (RString, [AHive; ANode "node"]),
172 "return the name of the node",
174 Return the name of the node.
176 Note that the name of the root node is a dummy, such as
177 C<$$$PROTO.HIV> (other names are possible: it seems to depend on the
178 tool or program that created the hive in the first place). You can
179 only know the \"real\" name of the root node by knowing which registry
180 file this hive originally comes from, which is knowledge that is
181 outside the scope of this library.";
183 "node_timestamp", (RInt64, [AHive; ANode "node"]),
184 "return the modification time of the node",
186 Return the modification time of the node.
188 The returned value is a Windows filetime.
189 To convert this to a Unix C<time_t> see:
190 L<http://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux/6161842#6161842>";
192 "node_children", (RNodeList, [AHive; ANode "node"]),
193 "return children of node",
195 Return an array of nodes which are the subkeys
196 (children) of C<node>.";
198 "node_get_child", (RNodeNotFound, [AHive; ANode "node"; AString "name"]),
199 "return named child of node",
201 Return the child of node with the name C<name>, if it exists.
203 The name is matched case insensitively.";
205 "node_parent", (RNode, [AHive; ANode "node"]),
206 "return the parent of node",
208 Return the parent of C<node>.
210 The parent pointer of the root node in registry files that we
211 have examined seems to be invalid, and so this function will
212 return an error if called on the root node.";
214 "node_values", (RValueList, [AHive; ANode "node"]),
215 "return (key, value) pairs attached to a node",
217 Return the array of (key, value) pairs attached to this node.";
219 "node_get_value", (RValue, [AHive; ANode "node"; AString "key"]),
220 "return named key at node",
222 Return the value attached to this node which has the name C<key>,
225 The key name is matched case insensitively.
227 Note that to get the default key, you should pass the empty
228 string C<\"\"> here. The default key is often written C<\"@\">, but
229 inside hives that has no meaning and won't give you the
232 "value_key_len", (RSize, [AHive; AValue "val"]),
233 "return the length of a value's key",
235 Return the length of the key (name) of a (key, value) pair. The
236 length can legitimately be 0, so errno is the necesary mechanism
239 In the context of Windows Registries, a zero-length name means
240 that this value is the default key for this node in the tree.
241 This is usually written as C<\"@\">.";
243 "value_key", (RString, [AHive; AValue "val"]),
244 "return the key of a (key, value) pair",
246 Return the key (name) of a (key, value) pair. The name
247 is reencoded as UTF-8 and returned as a string.
249 The string should be freed by the caller when it is no longer needed.
251 Note that this function can return a zero-length string. In the
252 context of Windows Registries, this means that this value is the
253 default key for this node in the tree. This is usually written
256 "value_type", (RLenType, [AHive; AValue "val"]),
257 "return data length and data type of a value",
259 Return the data length and data type of the value in this (key, value)
260 pair. See also C<hivex_value_value> which returns all this
261 information, and the value itself. Also, C<hivex_value_*> functions
262 below which can be used to return the value in a more useful form when
263 you know the type in advance.";
265 "node_struct_length", (RSize, [AHive; ANode "node"]),
266 "return the length of a node",
268 Return the length of the node data structure.";
270 "value_struct_length", (RSize, [AHive; AValue "val"]),
271 "return the length of a value data structure",
273 Return the length of the value data structure.";
275 "value_value", (RLenTypeVal, [AHive; AValue "val"]),
276 "return data length, data type and data of a value",
278 Return the value of this (key, value) pair. The value should
279 be interpreted according to its type (see C<hive_type>).";
281 "value_string", (RString, [AHive; AValue "val"]),
282 "return value as a string",
284 If this value is a string, return the string reencoded as UTF-8
285 (as a C string). This only works for values which have type
286 C<hive_t_string>, C<hive_t_expand_string> or C<hive_t_link>.";
288 "value_multiple_strings", (RStringList, [AHive; AValue "val"]),
289 "return value as multiple strings",
291 If this value is a multiple-string, return the strings reencoded
292 as UTF-8 (in C, as a NULL-terminated array of C strings, in other
293 language bindings, as a list of strings). This only
294 works for values which have type C<hive_t_multiple_strings>.";
296 "value_dword", (RInt32, [AHive; AValue "val"]),
297 "return value as a DWORD",
299 If this value is a DWORD (Windows int32), return it. This only works
300 for values which have type C<hive_t_dword> or C<hive_t_dword_be>.";
302 "value_qword", (RInt64, [AHive; AValue "val"]),
303 "return value as a QWORD",
305 If this value is a QWORD (Windows int64), return it. This only
306 works for values which have type C<hive_t_qword>.";
308 "commit", (RErr, [AHive; AStringNullable "filename"; AUnusedFlags]),
309 "commit (write) changes to file",
311 Commit (write) any changes which have been made.
313 C<filename> is the new file to write. If C<filename> is null/undefined
314 then we overwrite the original file (ie. the file name that was passed to
317 Note this does not close the hive handle. You can perform further
318 operations on the hive after committing, including making more
319 modifications. If you no longer wish to use the hive, then you
320 should close the handle after committing.";
322 "node_add_child", (RNode, [AHive; ANode "parent"; AString "name"]),
325 Add a new child node named C<name> to the existing node C<parent>.
326 The new child initially has no subnodes and contains no keys or
327 values. The sk-record (security descriptor) is inherited from
330 The parent must not have an existing child called C<name>, so if you
331 want to overwrite an existing child, call C<hivex_node_delete_child>
334 "node_delete_child", (RErr, [AHive; ANode "node"]),
337 Delete the node C<node>. All values at the node and all subnodes are
338 deleted (recursively). The C<node> handle and the handles of all
339 subnodes become invalid. You cannot delete the root node.";
341 "node_set_values", (RErr, [AHive; ANode "node"; ASetValues; AUnusedFlags]),
342 "set (key, value) pairs at a node",
344 This call can be used to set all the (key, value) pairs
347 C<node> is the node to modify.";
349 "node_set_value", (RErr, [AHive; ANode "node"; ASetValue; AUnusedFlags]),
350 "set a single (key, value) pair at a given node",
352 This call can be used to replace a single C<(key, value)> pair
353 stored in C<node>. If the key does not already exist, then a
354 new key is added. Key matching is case insensitive.
356 C<node> is the node to modify.";
360 * Note we don't want to use any external OCaml libraries which
361 * makes this a bit harder than it should be.
363 module StringMap = Map.Make (String)
365 let failwithf fs = ksprintf failwith fs
367 let unique = let i = ref 0 in fun () -> incr i; !i
369 let replace_char s c1 c2 =
370 let s2 = String.copy s in
372 for i = 0 to String.length s2 - 1 do
373 if String.unsafe_get s2 i = c1 then (
374 String.unsafe_set s2 i c2;
378 if not !r then s else s2
382 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
384 let triml ?(test = isspace) str =
386 let n = ref (String.length str) in
387 while !n > 0 && test str.[!i]; do
392 else String.sub str !i !n
394 let trimr ?(test = isspace) str =
395 let n = ref (String.length str) in
396 while !n > 0 && test str.[!n-1]; do
399 if !n = String.length str then str
400 else String.sub str 0 !n
402 let trim ?(test = isspace) str =
403 trimr ~test (triml ~test str)
405 (* Used to memoize the result of pod2text. *)
406 let pod2text_memo_filename = "generator/.pod2text.data.version.2"
407 let pod2text_memo : ((int option * bool * bool * string * string), string list) Hashtbl.t =
409 let chan = open_in pod2text_memo_filename in
410 let v = input_value chan in
414 _ -> Hashtbl.create 13
415 let pod2text_memo_updated () =
416 let chan = open_out pod2text_memo_filename in
417 output_value chan pod2text_memo;
420 (* Useful if you need the longdesc POD text as plain text. Returns a
423 * Because this is very slow (the slowest part of autogeneration),
424 * we memoize the results.
426 let pod2text ?width ?(trim = true) ?(discard = true) name longdesc =
427 let key = width, trim, discard, name, longdesc in
428 try Hashtbl.find pod2text_memo key
430 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
431 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
436 sprintf "pod2text -w %d %s" width (Filename.quote filename)
438 sprintf "pod2text %s" (Filename.quote filename) in
439 let chan = open_process_in cmd in
440 let lines = ref [] in
442 let line = input_line chan in
443 if i = 1 && discard then (* discard the first line of output *)
446 let line = if trim then triml line else line in
447 lines := line :: !lines;
450 let lines = try loop 1 with End_of_file -> List.rev !lines in
452 (match close_process_in chan with
455 failwithf "pod2text: process exited with non-zero status (%d)" i
456 | WSIGNALED i | WSTOPPED i ->
457 failwithf "pod2text: process signalled or stopped by signal %d" i
459 Hashtbl.add pod2text_memo key lines;
460 pod2text_memo_updated ();
464 let len = String.length s in
465 let sublen = String.length sub in
467 if i <= len-sublen then (
470 if s.[i+j] = sub.[j] then loop2 (j+1)
476 if r = -1 then loop (i+1) else r
482 let rec replace_str s s1 s2 =
483 let len = String.length s in
484 let sublen = String.length s1 in
488 let s' = String.sub s 0 i in
489 let s'' = String.sub s (i+sublen) (len-i-sublen) in
490 s' ^ s2 ^ replace_str s'' s1 s2
493 let rec string_split sep str =
494 let len = String.length str in
495 let seplen = String.length sep in
496 let i = find str sep in
499 let s' = String.sub str 0 i in
500 let s'' = String.sub str (i+seplen) (len-i-seplen) in
501 s' :: string_split sep s''
504 let files_equal n1 n2 =
505 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
506 match Sys.command cmd with
509 | i -> failwithf "%s: failed with error code %d" cmd i
511 let rec filter_map f = function
515 | Some y -> y :: filter_map f xs
516 | None -> filter_map f xs
518 let rec find_map f = function
519 | [] -> raise Not_found
523 | None -> find_map f xs
526 let rec loop i = function
528 | x :: xs -> f i x; loop (i+1) xs
533 let rec loop i = function
535 | x :: xs -> let r = f i x in r :: loop (i+1) xs
539 let count_chars c str =
541 for i = 0 to String.length str - 1 do
542 if c = String.unsafe_get str i then incr count
546 let name_of_argt = function
548 | ANode n | AValue n | AString n | AStringNullable n -> n
549 | AOpenFlags | AUnusedFlags -> "flags"
550 | ASetValues -> "values"
553 (* Check function names etc. for consistency. *)
554 let check_functions () =
555 let contains_uppercase str =
556 let len = String.length str in
558 if i >= len then false
561 if c >= 'A' && c <= 'Z' then true
568 (* Check function names. *)
570 fun (name, _, _, _) ->
571 if String.length name >= 7 && String.sub name 0 7 = "hivex" then
572 failwithf "function name %s does not need 'hivex' prefix" name;
574 failwithf "function name is empty";
575 if name.[0] < 'a' || name.[0] > 'z' then
576 failwithf "function name %s must start with lowercase a-z" name;
577 if String.contains name '-' then
578 failwithf "function name %s should not contain '-', use '_' instead."
582 (* Check function parameter/return names. *)
584 fun (name, style, _, _) ->
585 let check_arg_ret_name n =
586 if contains_uppercase n then
587 failwithf "%s param/ret %s should not contain uppercase chars"
589 if String.contains n '-' || String.contains n '_' then
590 failwithf "%s param/ret %s should not contain '-' or '_'"
593 failwithf "%s has a param/ret called 'value', which causes conflicts in the OCaml bindings, use something like 'val' or a more descriptive name" name;
594 if n = "int" || n = "char" || n = "short" || n = "long" then
595 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
596 if n = "i" || n = "n" then
597 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
598 if n = "argv" || n = "args" then
599 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
601 (* List Haskell, OCaml and C keywords here.
602 * http://www.haskell.org/haskellwiki/Keywords
603 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
604 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
605 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
606 * |perl -pe 's/(.+)/"$1";/'|fmt -70
607 * Omitting _-containing words, since they're handled above.
608 * Omitting the OCaml reserved word, "val", is ok,
609 * and saves us from renaming several parameters.
612 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
613 "char"; "class"; "const"; "constraint"; "continue"; "data";
614 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
615 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
616 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
617 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
618 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
620 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
621 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
622 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
623 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
624 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
625 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
626 "volatile"; "when"; "where"; "while";
628 if List.mem n reserved then
629 failwithf "%s has param/ret using reserved word %s" name n;
632 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
635 (* Check short descriptions. *)
637 fun (name, _, shortdesc, _) ->
638 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
639 failwithf "short description of %s should begin with lowercase." name;
640 let c = shortdesc.[String.length shortdesc-1] in
641 if c = '\n' || c = '.' then
642 failwithf "short description of %s should not end with . or \\n." name
645 (* Check long dscriptions. *)
647 fun (name, _, _, longdesc) ->
648 if longdesc.[String.length longdesc-1] = '\n' then
649 failwithf "long description of %s should not end with \\n." name
652 (* 'pr' prints to the current output file. *)
653 let chan = ref Pervasives.stdout
658 let i = count_chars '\n' str in
660 output_string !chan str
663 let copyright_years =
664 let this_year = 1900 + (localtime (time ())).tm_year in
665 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
667 (* Generate a header block in a number of standard styles. *)
669 | CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
671 type license = GPLv2plus | LGPLv2plus | GPLv2 | LGPLv2
673 let generate_header ?(extra_inputs = []) comment license =
674 let inputs = "generator/generator.ml" :: extra_inputs in
675 let c = match comment with
676 | CStyle -> pr "/* "; " *"
677 | CPlusPlusStyle -> pr "// "; "//"
678 | HashStyle -> pr "# "; "#"
679 | OCamlStyle -> pr "(* "; " *"
680 | HaskellStyle -> pr "{- "; " "
681 | PODCommentStyle -> pr "=begin comment\n\n "; "" in
682 pr "hivex generated file\n";
683 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
684 List.iter (pr "%s %s\n" c) inputs;
685 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
687 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
688 pr "%s Derived from code by Petter Nordahl-Hagen under a compatible license:\n" c;
689 pr "%s Copyright (c) 1997-2007 Petter Nordahl-Hagen.\n" c;
690 pr "%s Derived from code by Markus Stephany under a compatible license:\n" c;
691 pr "%s Copyright (c)2000-2004, Markus Stephany.\n" c;
695 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
696 pr "%s it under the terms of the GNU General Public License as published by\n" c;
697 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
698 pr "%s (at your option) any later version.\n" c;
700 pr "%s This program is distributed in the hope that it will be useful,\n" c;
701 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
702 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
703 pr "%s GNU General Public License for more details.\n" c;
705 pr "%s You should have received a copy of the GNU General Public License along\n" c;
706 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
707 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
710 pr "%s This library is free software; you can redistribute it and/or\n" c;
711 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
712 pr "%s License as published by the Free Software Foundation; either\n" c;
713 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
715 pr "%s This library is distributed in the hope that it will be useful,\n" c;
716 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
717 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
718 pr "%s Lesser General Public License for more details.\n" c;
720 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
721 pr "%s License along with this library; if not, write to the Free Software\n" c;
722 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
725 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
726 pr "%s it under the terms of the GNU General Public License as published by\n" c;
727 pr "%s the Free Software Foundation; version 2 of the License only.\n" c;
729 pr "%s This program is distributed in the hope that it will be useful,\n" c;
730 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
731 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
732 pr "%s GNU General Public License for more details.\n" c;
734 pr "%s You should have received a copy of the GNU General Public License along\n" c;
735 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
736 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
739 pr "%s This library is free software; you can redistribute it and/or\n" c;
740 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
741 pr "%s License as published by the Free Software Foundation;\n" c;
742 pr "%s version 2.1 of the License only.\n" c;
744 pr "%s This library is distributed in the hope that it will be useful,\n" c;
745 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
746 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
747 pr "%s Lesser General Public License for more details.\n" c;
749 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
750 pr "%s License along with this library; if not, write to the Free Software\n" c;
751 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
754 | CStyle -> pr " */\n"
757 | OCamlStyle -> pr " *)\n"
758 | HaskellStyle -> pr "-}\n"
759 | PODCommentStyle -> pr "\n=end comment\n"
763 (* Start of main code generation functions below this line. *)
765 let rec generate_c_header () =
766 generate_header CStyle LGPLv2;
779 /* NOTE: This API is documented in the man page hivex(3). */
782 typedef struct hive_h hive_h;
784 /* Nodes and values. */
785 typedef size_t hive_node_h;
786 typedef size_t hive_value_h;
790 # define HIVEX_NO_KEY ENOKEY
792 # define HIVEX_NO_KEY ENOENT
795 /* Pre-defined types. */
799 fun (t, old_style, new_style, description) ->
800 pr " /* %s */\n" description;
801 pr " hive_t_REG_%s,\n" new_style;
802 pr "#define hive_t_%s hive_t_REG_%s\n" old_style new_style;
808 typedef enum hive_type hive_type;
810 /* Bitmask of flags passed to hivex_open. */
813 fun (v, flag, description) ->
814 pr " /* %s */\n" description;
815 pr "#define HIVEX_OPEN_%-10s %d\n" flag v;
820 /* Array of (key, value) pairs passed to hivex_node_set_values. */
821 struct hive_set_value {
827 typedef struct hive_set_value hive_set_value;
831 pr "/* Functions. */\n";
833 (* Function declarations. *)
835 fun (shortname, style, _, _) ->
836 let name = "hivex_" ^ shortname in
837 generate_c_prototype ~extern:true name style
840 (* The visitor pattern. *)
842 /* Visit all nodes. This is specific to the C API and is not made
843 * available to other languages. This is because of the complexity
844 * of binding callbacks in other languages, but also because other
845 * languages make it much simpler to iterate over a tree.
847 struct hivex_visitor {
848 int (*node_start) (hive_h *, void *opaque, hive_node_h, const char *name);
849 int (*node_end) (hive_h *, void *opaque, hive_node_h, const char *name);
850 int (*value_string) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *str);
851 int (*value_multiple_strings) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, char **argv);
852 int (*value_string_invalid_utf16) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *str);
853 int (*value_dword) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, int32_t);
854 int (*value_qword) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, int64_t);
855 int (*value_binary) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *value);
856 int (*value_none) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *value);
857 int (*value_other) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *value);
858 int (*value_any) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *value);
861 #define HIVEX_VISIT_SKIP_BAD 1
863 extern int hivex_visit (hive_h *h, const struct hivex_visitor *visitor, size_t len, void *opaque, int flags);
864 extern int hivex_visit_node (hive_h *h, hive_node_h node, const struct hivex_visitor *visitor, size_t len, void *opaque, int flags);
868 (* Finish the header file. *)
874 #endif /* HIVEX_H_ */
877 and generate_c_prototype ?(extern = false) name style =
878 if extern then pr "extern ";
879 (match fst style with
881 | RErrDispose -> pr "int "
882 | RHive -> pr "hive_h *"
883 | RSize -> pr "size_t "
884 | RNode -> pr "hive_node_h "
885 | RNodeNotFound -> pr "hive_node_h "
886 | RNodeList -> pr "hive_node_h *"
887 | RValue -> pr "hive_value_h "
888 | RValueList -> pr "hive_value_h *"
889 | RString -> pr "char *"
890 | RStringList -> pr "char **"
891 | RLenType -> pr "int "
892 | RLenTypeVal -> pr "char *"
893 | RInt32 -> pr "int32_t "
894 | RInt64 -> pr "int64_t "
897 let comma = ref false in
900 if !comma then pr ", "; comma := true;
902 | AHive -> pr "hive_h *h"
903 | ANode n -> pr "hive_node_h %s" n
904 | AValue n -> pr "hive_value_h %s" n
905 | AString n | AStringNullable n -> pr "const char *%s" n
906 | AOpenFlags | AUnusedFlags -> pr "int flags"
907 | ASetValues -> pr "size_t nr_values, const hive_set_value *values"
908 | ASetValue -> pr "const hive_set_value *val"
910 (match fst style with
911 | RLenType | RLenTypeVal -> pr ", hive_type *t, size_t *len"
916 and generate_c_pod () =
917 generate_header PODCommentStyle GPLv2;
924 hivex - Windows Registry \"hive\" extraction library
932 fun (shortname, style, _, _) ->
933 let name = "hivex_" ^ shortname in
935 generate_c_prototype ~extern:false name style;
940 Link with I<-lhivex>.
944 Hivex is a library for extracting the contents of Windows Registry
945 \"hive\" files. It is designed to be secure against buggy or malicious
948 Unlike other tools in this area, it doesn't use the textual .REG
949 format, because parsing that is as much trouble as parsing the
950 original binary format. Instead it makes the file available
951 through a C API, and then wraps this API in higher level scripting
954 There is a separate program to export the hive as XML
955 (see L<hivexml(1)>), or to navigate the file (see L<hivexsh(1)>).
956 There is also a Perl script to export and merge the
957 file as a textual .REG (regedit) file, see L<hivexregedit(1)>.
959 If you just want to export or modify the Registry of a Windows
960 virtual machine, you should look at L<virt-win-reg(1)>.
962 Hivex is also comes with language bindings for
963 OCaml, Perl, Python and Ruby.
969 This handle describes an open hive file.
971 =head2 C<hive_node_h>
973 This is a node handle, an integer but opaque outside the library.
974 Valid node handles cannot be 0. The library returns 0 in some
975 situations to indicate an error.
979 The enum below describes the possible types for the value(s)
980 stored at each node. Note that you should not trust the
981 type field in a Windows Registry, as it very often has no
982 relationship to reality. Some applications use their own
983 types. The encoding of strings is not specified. Some
984 programs store everything (including strings) in binary blobs.
989 fun (t, _, new_style, description) ->
990 pr " /* %s */\n" description;
991 pr " hive_t_REG_%s = %d,\n" new_style t
996 =head2 C<hive_value_h>
998 This is a value handle, an integer but opaque outside the library.
999 Valid value handles cannot be 0. The library returns 0 in some
1000 situations to indicate an error.
1002 =head2 C<hive_set_value>
1004 The typedef C<hive_set_value> is used in conjunction with the
1005 C<hivex_node_set_values> call described below.
1007 struct hive_set_value {
1008 char *key; /* key - a UTF-8 encoded ASCIIZ string */
1009 hive_type t; /* type of value field */
1010 size_t len; /* length of value field in bytes */
1011 char *value; /* value field */
1013 typedef struct hive_set_value hive_set_value;
1015 To set the default value for a node, you have to pass C<key = \"\">.
1017 Note that the C<value> field is just treated as a list of bytes, and
1018 is stored directly in the hive. The caller has to ensure correct
1019 encoding and endianness, for example converting dwords to little
1022 The correct type and encoding for values depends on the node and key
1023 in the registry, the version of Windows, and sometimes even changes
1024 between versions of Windows for the same key. We don't document it
1025 here. Often it's not documented at all.
1031 fun (shortname, style, _, longdesc) ->
1032 let name = "hivex_" ^ shortname in
1033 pr "=head2 %s\n" name;
1035 generate_c_prototype ~extern:false name style;
1040 if List.mem AUnusedFlags (snd style) then
1041 pr "The flags parameter is unused. Always pass 0.\n\n";
1043 if List.mem ASetValues (snd style) then
1044 pr "C<values> is an array of (key, value) pairs. There
1045 should be C<nr_values> elements in this array.
1047 Any existing values stored at the node are discarded, and their
1048 C<hive_value_h> handles become invalid. Thus you can remove all
1049 values stored at C<node> by passing C<nr_values = 0>.\n\n";
1051 if List.mem ASetValue (snd style) then
1052 pr "C<value> is a single (key, value) pair.
1054 Existing C<hive_value_h> handles become invalid.\n\n";
1056 (match fst style with
1059 Returns 0 on success.
1060 On error this returns -1 and sets errno.\n\n"
1063 Returns 0 on success.
1064 On error this returns -1 and sets errno.
1066 This function frees the hive handle (even if it returns an error).
1067 The hive handle must not be used again after calling this function.\n\n"
1070 Returns a new hive handle.
1071 On error this returns NULL and sets errno.\n\n"
1075 On error this returns 0 and sets errno.\n\n"
1078 Returns a node handle.
1079 On error this returns 0 and sets errno.\n\n"
1082 Returns a node handle.
1083 If the node was not found, this returns 0 without setting errno.
1084 On error this returns 0 and sets errno.\n\n"
1087 Returns a 0-terminated array of nodes.
1088 The array must be freed by the caller when it is no longer needed.
1089 On error this returns NULL and sets errno.\n\n"
1092 Returns a value handle.
1093 On error this returns 0 and sets errno.\n\n"
1096 Returns a 0-terminated array of values.
1097 The array must be freed by the caller when it is no longer needed.
1098 On error this returns NULL and sets errno.\n\n"
1102 The string must be freed by the caller when it is no longer needed.
1103 On error this returns NULL and sets errno.\n\n"
1106 Returns a NULL-terminated array of C strings.
1107 The strings and the array must all be freed by the caller when
1108 they are no longer needed.
1109 On error this returns NULL and sets errno.\n\n"
1112 Returns 0 on success.
1113 On error this returns -1 and sets errno.\n\n"
1116 The value is returned as an array of bytes (of length C<len>).
1117 The value must be freed by the caller when it is no longer needed.
1118 On error this returns NULL and sets errno.\n\n"
1119 | RInt32 | RInt64 -> ()
1124 =head1 WRITING TO HIVE FILES
1126 The hivex library supports making limited modifications to hive files.
1127 We have tried to implement this very conservatively in order to reduce
1128 the chance of corrupting your registry. However you should be careful
1129 and take back-ups, since Microsoft has never documented the hive
1130 format, and so it is possible there are nuances in the
1131 reverse-engineered format that we do not understand.
1133 To be able to modify a hive, you must pass the C<HIVEX_OPEN_WRITE>
1134 flag to C<hivex_open>, otherwise any write operation will return with
1137 The write operations shown below do not modify the on-disk file
1138 immediately. You must call C<hivex_commit> in order to write the
1139 changes to disk. If you call C<hivex_close> without committing then
1140 any writes are discarded.
1142 Hive files internally consist of a \"memory dump\" of binary blocks
1143 (like the C heap), and some of these blocks can be unused. The hivex
1144 library never reuses these unused blocks. Instead, to ensure
1145 robustness in the face of the partially understood on-disk format,
1146 hivex only allocates new blocks after the end of the file, and makes
1147 minimal modifications to existing structures in the file to point to
1148 these new blocks. This makes hivex slightly less disk-efficient than
1149 it could be, but disk is cheap, and registry modifications tend to be
1152 When deleting nodes, it is possible that this library may leave
1153 unreachable live blocks in the hive. This is because certain parts of
1154 the hive disk format such as security (sk) records and big data (db)
1155 records and classname fields are not well understood (and not
1156 documented at all) and we play it safe by not attempting to modify
1157 them. Apart from wasting a little bit of disk space, it is not
1158 thought that unreachable blocks are a problem.
1160 =head2 WRITE OPERATIONS WHICH ARE NOT SUPPORTED
1166 Changing the root node.
1170 Creating a new hive file from scratch. This is impossible at present
1171 because not all fields in the header are understood. In the hivex
1172 source tree is a file called C<images/minimal> which could be used as
1173 the basis for a new hive (but I<caveat emptor>).
1177 Modifying or deleting single values at a node.
1181 Modifying security key (sk) records or classnames.
1182 Previously we did not understand these records. However now they
1183 are well-understood and we could add support if it was required
1184 (but nothing much really uses them).
1188 =head1 VISITING ALL NODES
1190 The visitor pattern is useful if you want to visit all nodes
1191 in the tree or all nodes below a certain point in the tree.
1193 First you set up your own C<struct hivex_visitor> with your
1196 Each of these callback functions should return 0 on success or -1
1197 on error. If any callback returns -1, then the entire visit
1198 terminates immediately. If you don't need a callback function at
1199 all, set the function pointer to NULL.
1201 struct hivex_visitor {
1202 int (*node_start) (hive_h *, void *opaque, hive_node_h, const char *name);
1203 int (*node_end) (hive_h *, void *opaque, hive_node_h, const char *name);
1204 int (*value_string) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1205 hive_type t, size_t len, const char *key, const char *str);
1206 int (*value_multiple_strings) (hive_h *, void *opaque, hive_node_h,
1207 hive_value_h, hive_type t, size_t len, const char *key, char **argv);
1208 int (*value_string_invalid_utf16) (hive_h *, void *opaque, hive_node_h,
1209 hive_value_h, hive_type t, size_t len, const char *key,
1211 int (*value_dword) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1212 hive_type t, size_t len, const char *key, int32_t);
1213 int (*value_qword) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1214 hive_type t, size_t len, const char *key, int64_t);
1215 int (*value_binary) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1216 hive_type t, size_t len, const char *key, const char *value);
1217 int (*value_none) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1218 hive_type t, size_t len, const char *key, const char *value);
1219 int (*value_other) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1220 hive_type t, size_t len, const char *key, const char *value);
1221 /* If value_any callback is not NULL, then the other value_*
1222 * callbacks are not used, and value_any is called on all values.
1224 int (*value_any) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1225 hive_type t, size_t len, const char *key, const char *value);
1232 int hivex_visit (hive_h *h, const struct hivex_visitor *visitor, size_t len, void *opaque, int flags);
1234 Visit all the nodes recursively in the hive C<h>.
1236 C<visitor> should be a C<hivex_visitor> structure with callback
1237 fields filled in as required (unwanted callbacks can be set to
1238 NULL). C<len> must be the length of the 'visitor' struct (you
1239 should pass C<sizeof (struct hivex_visitor)> for this).
1241 This returns 0 if the whole recursive visit was completed
1242 successfully. On error this returns -1. If one of the callback
1243 functions returned an error than we don't touch errno. If the
1244 error was generated internally then we set errno.
1246 You can skip bad registry entries by setting C<flag> to
1247 C<HIVEX_VISIT_SKIP_BAD>. If this flag is not set, then a bad registry
1248 causes the function to return an error immediately.
1250 This function is robust if the registry contains cycles or
1251 pointers which are invalid or outside the registry. It detects
1252 these cases and returns an error.
1254 =item hivex_visit_node
1256 int hivex_visit_node (hive_h *h, hive_node_h node, const struct hivex_visitor *visitor, size_t len, void *opaque);
1258 Same as C<hivex_visit> but instead of starting out at the root, this
1263 =head1 THE STRUCTURE OF THE WINDOWS REGISTRY
1265 Note: To understand the relationship between hives and the common
1266 Windows Registry keys (like C<HKEY_LOCAL_MACHINE>) please see the
1267 Wikipedia page on the Windows Registry.
1269 The Windows Registry is split across various binary files, each
1270 file being known as a \"hive\". This library only handles a single
1271 hive file at a time.
1273 Hives are n-ary trees with a single root. Each node in the tree
1276 Each node in the tree (including non-leaf nodes) may have an
1277 arbitrary list of (key, value) pairs attached to it. It may
1278 be the case that one of these pairs has an empty key. This
1279 is referred to as the default key for the node.
1281 The (key, value) pairs are the place where the useful data is
1282 stored in the registry. The key is always a string (possibly the
1283 empty string for the default key). The value is a typed object
1284 (eg. string, int32, binary, etc.).
1286 =head2 RELATIONSHIP TO .REG FILES
1288 The hivex C library does not care about or deal with Windows .REG
1289 files. Instead we push this complexity up to the Perl
1290 L<Win::Hivex(3)> library and the Perl programs
1291 L<hivexregedit(1)> and L<virt-win-reg(1)>.
1292 Nevertheless it is useful to look at the relationship between the
1293 Registry and .REG files because they are so common.
1295 A .REG file is a textual representation of the registry, or part of the
1296 registry. The actual registry hives that Windows uses are binary
1297 files. There are a number of Windows and Linux tools that let you
1298 generate .REG files, or merge .REG files back into the registry hives.
1299 Notable amongst them is Microsoft's REGEDIT program (formerly known as
1302 A typical .REG file will contain many sections looking like this:
1304 [HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\Stack]
1305 \"@\"=\"Generic Stack\"
1306 \"TileInfo\"=\"prop:System.FileCount\"
1307 \"TilePath\"=str(2):\"%%systemroot%%\\\\system32\"
1308 \"ThumbnailCutoff\"=dword:00000000
1309 \"FriendlyTypeName\"=hex(2):40,00,25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,\\
1310 6f,00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,\\
1311 33,00,32,00,5c,00,73,00,65,00,61,00,72,00,63,00,68,00,66,00,\\
1312 6f,00,6c,00,64,00,65,00,72,00,2e,00,64,00,6c,00,6c,00,2c,00,\\
1313 2d,00,39,00,30,00,32,00,38,00,00,00,d8
1315 Taking this one piece at a time:
1317 [HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\Stack]
1319 This is the path to this node in the registry tree. The first part,
1320 C<HKEY_LOCAL_MACHINE\\SOFTWARE> means that this comes from a hive
1321 file called C<C:\\WINDOWS\\SYSTEM32\\CONFIG\\SOFTWARE>.
1322 C<\\Classes\\Stack> is the real path part,
1323 starting at the root node of the C<SOFTWARE> hive.
1325 Below the node name is a list of zero or more key-value pairs. Any
1326 interior or leaf node in the registry may have key-value pairs
1329 \"@\"=\"Generic Stack\"
1331 This is the \"default key\". In reality (ie. inside the binary hive)
1332 the key string is the empty string. In .REG files this is written as
1333 C<@> but this has no meaning either in the hives themselves or in this
1334 library. The value is a string (type 1 - see C<enum hive_type>
1337 \"TileInfo\"=\"prop:System.FileCount\"
1339 This is a regular (key, value) pair, with the value being a type 1
1340 string. Note that inside the binary file the string is likely to be
1341 UTF-16LE encoded. This library converts to and from UTF-8 strings
1342 transparently in some cases.
1344 \"TilePath\"=str(2):\"%%systemroot%%\\\\system32\"
1346 The value in this case has type 2 (expanded string) meaning that some
1347 %%...%% variables get expanded by Windows. (This library doesn't know
1348 or care about variable expansion).
1350 \"ThumbnailCutoff\"=dword:00000000
1352 The value in this case is a dword (type 4).
1354 \"FriendlyTypeName\"=hex(2):40,00,....
1356 This value is an expanded string (type 2) represented in the .REG file
1357 as a series of hex bytes. In this case the string appears to be a
1360 =head1 NOTE ON THE USE OF ERRNO
1362 Many functions in this library set errno to indicate errors. These
1363 are the values of errno you may encounter (this list is not
1370 Corrupt or unsupported Registry file format.
1378 Passed an invalid argument to the function.
1382 Followed a Registry pointer which goes outside
1383 the registry or outside a registry block.
1387 Registry contains cycles.
1391 Field in the registry out of range.
1395 Registry key already exists.
1399 Tried to write to a registry which is not opened for writing.
1403 =head1 ENVIRONMENT VARIABLES
1409 Setting HIVEX_DEBUG=1 will enable very verbose messages. This is
1410 useful for debugging problems with the library itself.
1423 L<http://libguestfs.org/>,
1426 L<http://en.wikipedia.org/wiki/Windows_Registry>.
1430 Richard W.M. Jones (C<rjones at redhat dot com>)
1434 Copyright (C) 2009-2010 Red Hat Inc.
1436 Derived from code by Petter Nordahl-Hagen under a compatible license:
1437 Copyright (C) 1997-2007 Petter Nordahl-Hagen.
1439 Derived from code by Markus Stephany under a compatible license:
1440 Copyright (C) 2000-2004 Markus Stephany.
1442 This library is free software; you can redistribute it and/or
1443 modify it under the terms of the GNU Lesser General Public
1444 License as published by the Free Software Foundation;
1445 version 2.1 of the License only.
1447 This library is distributed in the hope that it will be useful,
1448 but WITHOUT ANY WARRANTY; without even the implied warranty of
1449 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1450 Lesser General Public License for more details.
1453 (* Generate the linker script which controls the visibility of
1454 * symbols in the public ABI and ensures no other symbols get
1455 * exported accidentally.
1457 and generate_linker_script () =
1458 generate_header HashStyle GPLv2plus;
1466 List.map (fun (name, _, _, _) -> "hivex_" ^ name)
1468 let globals = List.sort compare (globals @ functions) in
1472 List.iter (pr " %s;\n") globals;
1479 and generate_ocaml_interface () =
1480 generate_header OCamlStyle LGPLv2plus;
1484 (** A [hive_h] hive file handle. *)
1488 (** Nodes and values. *)
1490 exception Error of string * Unix.error * string
1491 (** Error raised by a function.
1493 The first parameter is the name of the function which raised the error.
1494 The second parameter is the errno (see the [Unix] module). The third
1495 parameter is a human-readable string corresponding to the errno.
1497 See hivex(3) for a partial list of interesting errno values that
1498 can be generated by the library. *)
1499 exception Handle_closed of string
1500 (** This exception is raised if you call a function on a closed handle. *)
1506 fun (t, _, new_style, description) ->
1508 pr " | REG_%s (** %s *)\n" new_style description
1512 | REG_UNKNOWN of int32 (** unknown type *)
1513 (** Hive type field. *)
1519 fun (v, flag, description) ->
1520 assert (1 lsl i = v);
1521 pr " | OPEN_%s (** %s *)\n" flag description
1525 (** Open flags for {!open_file} call. *)
1532 (** (key, value) pair passed (as an array) to {!node_set_values}. *)
1536 fun (name, style, shortdesc, _) ->
1538 generate_ocaml_prototype name style;
1539 pr "(** %s *)\n" shortdesc
1542 and generate_ocaml_implementation () =
1543 generate_header OCamlStyle LGPLv2plus;
1550 exception Error of string * Unix.error * string
1551 exception Handle_closed of string
1553 (* Give the exceptions names, so they can be raised from the C code. *)
1555 Callback.register_exception \"ocaml_hivex_error\"
1556 (Error (\"\", Unix.EUNKNOWNERR 0, \"\"));
1557 Callback.register_exception \"ocaml_hivex_closed\" (Handle_closed \"\")
1563 fun (t, _, new_style, _) ->
1565 pr " | REG_%s\n" new_style
1569 | REG_UNKNOWN of int32
1575 fun (v, flag, description) ->
1576 assert (1 lsl i = v);
1577 pr " | OPEN_%s (** %s *)\n" flag description
1591 fun (name, style, _, _) ->
1592 generate_ocaml_prototype ~is_external:true name style
1595 and generate_ocaml_prototype ?(is_external = false) name style =
1596 let ocaml_name = if name = "open" then "open_file" else name in
1598 if is_external then pr "external " else pr "val ";
1599 pr "%s : " ocaml_name;
1602 | AHive -> pr "t -> "
1603 | ANode _ -> pr "node -> "
1604 | AValue _ -> pr "value -> "
1605 | AString _ -> pr "string -> "
1606 | AStringNullable _ -> pr "string option -> "
1607 | AOpenFlags -> pr "open_flag list -> "
1608 | AUnusedFlags -> ()
1609 | ASetValues -> pr "set_value array -> "
1610 | ASetValue -> pr "set_value -> "
1612 (match fst style with
1613 | RErr -> pr "unit" (* all errors are turned into exceptions *)
1614 | RErrDispose -> pr "unit"
1616 | RSize -> pr "int64"
1617 | RNode -> pr "node"
1618 | RNodeNotFound -> pr "node"
1619 | RNodeList -> pr "node array"
1620 | RValue -> pr "value"
1621 | RValueList -> pr "value array"
1622 | RString -> pr "string"
1623 | RStringList -> pr "string array"
1624 | RLenType -> pr "hive_type * int"
1625 | RLenTypeVal -> pr "hive_type * string"
1626 | RInt32 -> pr "int32"
1627 | RInt64 -> pr "int64"
1630 pr " = \"ocaml_hivex_%s\"" name;
1633 and generate_ocaml_c () =
1634 generate_header CStyle LGPLv2plus;
1645 #include <caml/config.h>
1646 #include <caml/alloc.h>
1647 #include <caml/callback.h>
1648 #include <caml/custom.h>
1649 #include <caml/fail.h>
1650 #include <caml/memory.h>
1651 #include <caml/mlvalues.h>
1652 #include <caml/signals.h>
1654 #ifdef HAVE_CAML_UNIXSUPPORT_H
1655 #include <caml/unixsupport.h>
1657 extern value unix_error_of_code (int errcode);
1660 #ifndef HAVE_CAML_RAISE_WITH_ARGS
1662 caml_raise_with_args (value tag, int nargs, value args[])
1665 CAMLxparamN (args, nargs);
1669 bucket = caml_alloc_small (1 + nargs, 0);
1670 Field(bucket, 0) = tag;
1671 for (i = 0; i < nargs; i++) Field(bucket, 1 + i) = args[i];
1679 #define Hiveh_val(v) (*((hive_h **)Data_custom_val(v)))
1680 static value Val_hiveh (hive_h *);
1681 static int HiveOpenFlags_val (value);
1682 static hive_set_value *HiveSetValue_val (value);
1683 static hive_set_value *HiveSetValues_val (value);
1684 static hive_type HiveType_val (value);
1685 static value Val_hive_type (hive_type);
1686 static value copy_int_array (size_t *);
1687 static value copy_type_len (size_t, hive_type);
1688 static value copy_type_value (const char *, size_t, hive_type);
1689 static void raise_error (const char *) Noreturn;
1690 static void raise_closed (const char *) Noreturn;
1696 fun (name, style, _, _) ->
1697 pr "/* Automatically generated wrapper for function\n";
1698 pr " * "; generate_ocaml_prototype name style;
1704 | ASetValues -> ["nrvalues"; "values"]
1705 | AUnusedFlags -> ["0"]
1706 | arg -> [name_of_argt arg]) (snd style) in
1708 match fst style with
1709 | RLenType | RLenTypeVal -> c_params @ [["&t"; "&len"]]
1711 let c_params = List.concat c_params in
1714 filter_map (function
1715 | AUnusedFlags -> None
1716 | arg -> Some (name_of_argt arg ^ "v")) (snd style) in
1718 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
1719 pr "CAMLprim value ocaml_hivex_%s (value %s" name (List.hd params);
1720 List.iter (pr ", value %s") (List.tl params); pr ");\n";
1723 pr "CAMLprim value\n";
1724 pr "ocaml_hivex_%s (value %s" name (List.hd params);
1725 List.iter (pr ", value %s") (List.tl params);
1729 pr " CAMLparam%d (%s);\n"
1730 (List.length params) (String.concat ", " params);
1731 pr " CAMLlocal1 (rv);\n";
1737 pr " hive_h *h = Hiveh_val (hv);\n";
1738 pr " if (h == NULL)\n";
1739 pr " raise_closed (\"%s\");\n" name
1741 pr " hive_node_h %s = Int_val (%sv);\n" n n
1743 pr " hive_value_h %s = Int_val (%sv);\n" n n
1745 pr " const char *%s = String_val (%sv);\n" n n
1746 | AStringNullable n ->
1747 pr " const char *%s =\n" n;
1748 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
1751 pr " int flags = HiveOpenFlags_val (flagsv);\n"
1752 | AUnusedFlags -> ()
1754 pr " int nrvalues = Wosize_val (valuesv);\n";
1755 pr " hive_set_value *values = HiveSetValues_val (valuesv);\n"
1757 pr " hive_set_value *val = HiveSetValue_val (valv);\n"
1762 match fst style with
1763 | RErr -> pr " int r;\n"; "-1"
1764 | RErrDispose -> pr " int r;\n"; "-1"
1765 | RHive -> pr " hive_h *r;\n"; "NULL"
1766 | RSize -> pr " size_t r;\n"; "0"
1767 | RNode -> pr " hive_node_h r;\n"; "0"
1770 pr " hive_node_h r;\n";
1772 | RNodeList -> pr " hive_node_h *r;\n"; "NULL"
1773 | RValue -> pr " hive_value_h r;\n"; "0"
1774 | RValueList -> pr " hive_value_h *r;\n"; "NULL"
1775 | RString -> pr " char *r;\n"; "NULL"
1776 | RStringList -> pr " char **r;\n"; "NULL"
1779 pr " size_t len;\n";
1780 pr " hive_type t;\n";
1784 pr " size_t len;\n";
1785 pr " hive_type t;\n";
1794 "-1 && errno != 0" in
1796 (* The libguestfs OCaml bindings call enter_blocking_section
1797 * here. However I don't think that is safe, because we are
1798 * holding pointers to caml strings during the call, and these
1799 * could be moved or freed by other threads. In any case, there
1800 * is very little reason to enter_blocking_section for any hivex
1801 * call, so don't do it. XXX
1803 (*pr " caml_enter_blocking_section ();\n";*)
1804 pr " r = hivex_%s (%s" name (List.hd c_params);
1805 List.iter (pr ", %s") (List.tl c_params);
1807 (*pr " caml_leave_blocking_section ();\n";*)
1810 (* Dispose of the hive handle (even if hivex_close returns error). *)
1811 (match fst style with
1813 pr " /* So we don't double-free in the finalizer. */\n";
1814 pr " Hiveh_val (hv) = NULL;\n";
1821 | AHive | ANode _ | AValue _ | AString _ | AStringNullable _
1822 | AOpenFlags | AUnusedFlags -> ()
1824 pr " free (values);\n";
1827 pr " free (val);\n";
1831 (* Check for errors. *)
1832 pr " if (r == %s)\n" error_code;
1833 pr " raise_error (\"%s\");\n" name;
1836 (match fst style with
1837 | RErr -> pr " rv = Val_unit;\n"
1838 | RErrDispose -> pr " rv = Val_unit;\n"
1839 | RHive -> pr " rv = Val_hiveh (r);\n"
1840 | RSize -> pr " rv = caml_copy_int64 (r);\n"
1841 | RNode -> pr " rv = Val_int (r);\n"
1843 pr " if (r == 0)\n";
1844 pr " caml_raise_not_found ();\n";
1846 pr " rv = Val_int (r);\n"
1848 pr " rv = copy_int_array (r);\n";
1850 | RValue -> pr " rv = Val_int (r);\n"
1852 pr " rv = copy_int_array (r);\n";
1855 pr " rv = caml_copy_string (r);\n";
1858 pr " rv = caml_copy_string_array ((const char **) r);\n";
1859 pr " for (int i = 0; r[i] != NULL; ++i) free (r[i]);\n";
1861 | RLenType -> pr " rv = copy_type_len (len, t);\n"
1863 pr " rv = copy_type_value (r, len, t);\n";
1865 | RInt32 -> pr " rv = caml_copy_int32 (r);\n"
1866 | RInt64 -> pr " rv = caml_copy_int64 (r);\n"
1869 pr " CAMLreturn (rv);\n";
1877 HiveOpenFlags_val (value v)
1882 while (v != Val_int (0)) {
1884 flags |= 1 << Int_val (v2);
1891 static hive_set_value *
1892 HiveSetValue_val (value v)
1894 hive_set_value *val = malloc (sizeof (hive_set_value));
1896 val->key = String_val (Field (v, 0));
1897 val->t = HiveType_val (Field (v, 1));
1898 val->len = caml_string_length (Field (v, 2));
1899 val->value = String_val (Field (v, 2));
1904 static hive_set_value *
1905 HiveSetValues_val (value v)
1907 size_t nr_values = Wosize_val (v);
1908 hive_set_value *values = malloc (nr_values * sizeof (hive_set_value));
1912 for (i = 0; i < nr_values; ++i) {
1914 values[i].key = String_val (Field (v2, 0));
1915 values[i].t = HiveType_val (Field (v2, 1));
1916 values[i].len = caml_string_length (Field (v2, 2));
1917 values[i].value = String_val (Field (v2, 2));
1924 HiveType_val (value v)
1927 return Int_val (v); /* REG_NONE etc. */
1929 return Int32_val (Field (v, 0)); /* REG_UNKNOWN of int32 */
1933 Val_hive_type (hive_type t)
1939 CAMLreturn (Val_int (t));
1941 rv = caml_alloc (1, 0); /* REG_UNKNOWN of int32 */
1942 v = caml_copy_int32 (t);
1943 caml_modify (&Field (rv, 0), v);
1949 copy_int_array (size_t *xs)
1955 for (nr = 0; xs[nr] != 0; ++nr)
1958 CAMLreturn (Atom (0));
1960 rv = caml_alloc (nr, 0);
1961 for (i = 0; i < nr; ++i) {
1962 v = Val_int (xs[i]);
1963 Store_field (rv, i, v); /* Safe because v is not a block. */
1970 copy_type_len (size_t len, hive_type t)
1975 rv = caml_alloc (2, 0);
1976 v = Val_hive_type (t);
1977 Store_field (rv, 0, v);
1979 Store_field (rv, 1, v);
1984 copy_type_value (const char *r, size_t len, hive_type t)
1989 rv = caml_alloc (2, 0);
1990 v = Val_hive_type (t);
1991 Store_field (rv, 0, v);
1992 v = caml_alloc_string (len);
1993 memcpy (String_val (v), r, len);
1994 caml_modify (&Field (rv, 1), v);
1998 /* Raise exceptions. */
2000 raise_error (const char *function)
2002 /* Save errno early in case it gets trashed. */
2006 CAMLlocal3 (v1, v2, v3);
2008 v1 = caml_copy_string (function);
2009 v2 = unix_error_of_code (err);
2010 v3 = caml_copy_string (strerror (err));
2011 value vvv[] = { v1, v2, v3 };
2012 caml_raise_with_args (*caml_named_value (\"ocaml_hivex_error\"), 3, vvv);
2018 raise_closed (const char *function)
2023 v = caml_copy_string (function);
2024 caml_raise_with_arg (*caml_named_value (\"ocaml_hivex_closed\"), v);
2029 /* Allocate handles and deal with finalization. */
2031 hivex_finalize (value hv)
2033 hive_h *h = Hiveh_val (hv);
2034 if (h) hivex_close (h);
2037 static struct custom_operations hivex_custom_operations = {
2038 (char *) \"hivex_custom_operations\",
2040 custom_compare_default,
2041 custom_hash_default,
2042 custom_serialize_default,
2043 custom_deserialize_default
2047 Val_hiveh (hive_h *h)
2052 rv = caml_alloc_custom (&hivex_custom_operations,
2053 sizeof (hive_h *), 0, 1);
2060 and generate_perl_pm () =
2061 generate_header HashStyle LGPLv2plus;
2068 Win::Hivex - Perl bindings for reading and writing Windows Registry hive files
2074 $h = Win::Hivex->open ('SOFTWARE');
2075 $root_node = $h->root ();
2076 print $h->node_name ($root_node);
2080 The C<Win::Hivex> module provides a Perl XS binding to the
2081 L<hivex(3)> API for reading and writing Windows Registry binary
2086 All errors turn into calls to C<croak> (see L<Carp(3)>).
2100 XSLoader::load ('Win::Hivex');
2104 $h = Win::Hivex->open ($filename,";
2108 pr "\n [%s => 1,]" (String.lowercase flag)
2113 Open a Windows Registry binary hive file.
2115 The C<verbose> and C<debug> flags enable different levels of
2118 The C<write> flag is required if you will be modifying the
2119 hive file (see L<hivex(3)/WRITING TO HIVE FILES>).
2121 This function returns a hive handle. The hive handle is
2122 closed automatically when its reference count drops to 0.
2128 my $class = ref ($proto) || $proto;
2129 my $filename = shift;
2136 fun (n, flag, description) ->
2137 pr " # %s\n" description;
2138 pr " $flags += %d if $flags{%s};\n" n (String.lowercase flag)
2143 my $self = Win::Hivex::_open ($filename, $flags);
2144 bless $self, $class;
2151 fun (name, style, _, longdesc) ->
2152 (* The close call isn't explicit in Perl: handles are closed
2153 * when their reference count drops to 0.
2155 * The open call is coded specially in Perl.
2157 * Therefore we don't generate prototypes for these two calls:
2159 if fst style <> RErrDispose && List.hd (snd style) = AHive then (
2160 let longdesc = replace_str longdesc "C<hivex_" "C<" in
2161 pr "=item %s\n\n " name;
2162 generate_perl_prototype name style;
2164 pr "%s\n\n" longdesc;
2166 (match fst style with
2178 This returns a size.\n\n"
2181 This returns a node handle.\n\n"
2184 This returns a node handle, or C<undef> if the node was not found.\n\n"
2187 This returns a list of node handles.\n\n"
2190 This returns a value handle.\n\n"
2193 This returns a list of value handles.\n\n"
2196 if List.mem ASetValues (snd style) then
2197 pr "C<@values> is an array of (keys, value) pairs.
2198 Each element should be a hashref containing C<key>, C<t> (type)
2201 Any existing values stored at the node are discarded, and their
2202 C<value> handles become invalid. Thus you can remove all
2203 values stored at C<node> by passing C<@values = []>.\n\n"
2216 Copyright (C) %s Red Hat Inc.
2220 Please see the file COPYING.LIB for the full license.
2226 L<http://libguestfs.org>,
2232 and generate_perl_prototype name style =
2234 (match fst style with
2237 | RHive -> pr "$h = "
2238 | RSize -> pr "$size = "
2240 | RNodeNotFound -> pr "$node = "
2241 | RNodeList -> pr "@nodes = "
2242 | RValue -> pr "$value = "
2243 | RValueList -> pr "@values = "
2244 | RString -> pr "$string = "
2245 | RStringList -> pr "@strings = "
2246 | RLenType -> pr "($type, $len) = "
2247 | RLenTypeVal -> pr "($type, $data) = "
2248 | RInt32 -> pr "$int32 = "
2249 | RInt64 -> pr "$int64 = "
2252 let args = List.tl (snd style) in
2254 (* AUnusedFlags is dropped in the bindings. *)
2255 let args = List.filter ((<>) AUnusedFlags) args in
2259 let comma = ref false in
2262 if !comma then pr ", "; comma := true;
2267 | AString n -> pr "$%s" n
2268 | AStringNullable n -> pr "[$%s|undef]" n
2269 | AOpenFlags -> pr "[flags]"
2270 | AUnusedFlags -> assert false
2271 | ASetValues -> pr "\\@values"
2272 | ASetValue -> pr "$val"
2277 and generate_perl_xs () =
2278 generate_header CStyle LGPLv2plus;
2281 #include \"EXTERN.h\"
2287 #include <inttypes.h>
2290 my_newSVll(long long val) {
2291 #ifdef USE_64_BIT_ALL
2292 return newSViv(val);
2296 len = snprintf(buf, 100, \"%%\" PRId64, val);
2297 return newSVpv(buf, len);
2303 my_newSVull(unsigned long long val) {
2304 #ifdef USE_64_BIT_ALL
2305 return newSVuv(val);
2309 len = snprintf(buf, 100, \"%%\" PRIu64, val);
2310 return newSVpv(buf, len);
2316 /* http://www.perlmonks.org/?node_id=680842 */
2318 XS_unpack_charPtrPtr (SV *arg) {
2323 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
2324 croak (\"array reference expected\");
2326 av = (AV *)SvRV (arg);
2327 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
2329 croak (\"malloc failed\");
2331 for (i = 0; i <= av_len (av); i++) {
2332 SV **elem = av_fetch (av, i, 0);
2334 if (!elem || !*elem)
2335 croak (\"missing element in list\");
2337 ret[i] = SvPV_nolen (*elem);
2346 /* Handle set_values parameter. */
2347 typedef struct pl_set_values {
2349 hive_set_value *values;
2352 static pl_set_values
2353 unpack_pl_set_values (SV *sv)
2359 if (!sv || !SvOK (sv) || !SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV)
2360 croak (\"array reference expected\");
2362 av = (AV *)SvRV(sv);
2363 ret.nr_values = av_len (av) + 1;
2364 ret.values = malloc (ret.nr_values * sizeof (hive_set_value));
2366 croak (\"malloc failed\");
2368 for (i = 0; i <= av_len (av); i++) {
2369 SV **hvp = av_fetch (av, i, 0);
2371 if (!hvp || !*hvp || !SvROK (*hvp) || SvTYPE (SvRV (*hvp)) != SVt_PVHV)
2372 croak (\"missing element in list or not a hash ref\");
2374 HV *hv = (HV *)SvRV(*hvp);
2377 svp = hv_fetch (hv, \"key\", 3, 0);
2379 croak (\"missing 'key' in hash\");
2380 ret.values[i].key = SvPV_nolen (*svp);
2382 svp = hv_fetch (hv, \"t\", 1, 0);
2384 croak (\"missing 't' in hash\");
2385 ret.values[i].t = SvIV (*svp);
2387 svp = hv_fetch (hv, \"value\", 5, 0);
2389 croak (\"missing 'value' in hash\");
2390 ret.values[i].value = SvPV (*svp, ret.values[i].len);
2396 static hive_set_value *
2397 unpack_set_value (SV *sv)
2399 hive_set_value *ret;
2401 if (!sv || !SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVHV)
2402 croak (\"not a hash ref\");
2404 ret = malloc (sizeof (hive_set_value));
2406 croak (\"malloc failed\");
2408 HV *hv = (HV *)SvRV(sv);
2411 svp = hv_fetch (hv, \"key\", 3, 0);
2413 croak (\"missing 'key' in hash\");
2414 ret->key = SvPV_nolen (*svp);
2416 svp = hv_fetch (hv, \"t\", 1, 0);
2418 croak (\"missing 't' in hash\");
2419 ret->t = SvIV (*svp);
2421 svp = hv_fetch (hv, \"value\", 5, 0);
2423 croak (\"missing 'value' in hash\");
2424 ret->value = SvPV (*svp, ret->len);
2429 MODULE = Win::Hivex PACKAGE = Win::Hivex
2434 _open (filename, flags)
2438 RETVAL = hivex_open (filename, flags);
2440 croak (\"hivex_open: %%s: %%s\", filename, strerror (errno));
2448 if (hivex_close (h) == -1)
2449 croak (\"hivex_close: %%s\", strerror (errno));
2454 fun (name, style, _, longdesc) ->
2455 (* The close and open calls are handled specially above. *)
2456 if fst style <> RErrDispose && List.hd (snd style) = AHive then (
2457 (match fst style with
2458 | RErr -> pr "void\n"
2459 | RErrDispose -> failwith "perl bindings cannot handle a call which disposes of the handle"
2460 | RHive -> failwith "perl bindings cannot handle a call which returns a handle"
2465 | RString -> pr "SV *\n"
2470 | RLenTypeVal -> pr "void\n"
2471 | RInt32 -> pr "SV *\n"
2472 | RInt64 -> pr "SV *\n"
2475 (* Call and arguments. *)
2477 filter_map (function
2478 | AUnusedFlags -> None
2479 | arg -> Some (name_of_argt arg)) (snd style) in
2483 | AUnusedFlags -> "0"
2484 | ASetValues -> "values.nr_values, values.values"
2485 | arg -> name_of_argt arg) (snd style) in
2487 pr "%s (%s)\n" name (String.concat ", " perl_params);
2498 | AStringNullable n ->
2499 (* http://www.perlmonks.org/?node_id=554277 *)
2500 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n i i
2503 | AUnusedFlags -> ()
2505 pr " pl_set_values values = unpack_pl_set_values (ST(%d));\n" i
2507 pr " hive_set_value *val = unpack_set_value (ST(%d));\n" i
2514 pr " free (values.values);\n"
2517 | AHive | ANode _ | AValue _ | AString _ | AStringNullable _
2518 | AOpenFlags | AUnusedFlags -> ()
2523 (match fst style with
2528 pr " r = hivex_%s (%s);\n"
2529 name (String.concat ", " c_params);
2531 pr " if (r == -1)\n";
2532 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2535 | RErrDispose -> assert false
2536 | RHive -> assert false
2542 pr " /* hive_node_h = hive_value_h = size_t so we cheat\n";
2543 pr " here to simplify the generator */\n";
2546 pr " r = hivex_%s (%s);\n"
2547 name (String.concat ", " c_params);
2549 pr " if (r == 0)\n";
2550 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2552 pr " RETVAL = newSViv (r);\n";
2558 pr " hive_node_h r;\n";
2561 pr " r = hivex_%s (%s);\n"
2562 name (String.concat ", " c_params);
2564 pr " if (r == 0 && errno != 0)\n";
2565 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2567 pr " if (r == 0)\n";
2568 pr " RETVAL = &PL_sv_undef;\n";
2570 pr " RETVAL = newSViv (r);\n";
2578 pr " r = hivex_%s (%s);\n"
2579 name (String.concat ", " c_params);
2581 pr " if (r == NULL)\n";
2582 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2584 pr " RETVAL = newSVpv (r, 0);\n";
2595 pr " r = hivex_%s (%s);\n"
2596 name (String.concat ", " c_params);
2598 pr " if (r == NULL)\n";
2599 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2601 pr " for (n = 0; r[n] != 0; ++n) /**/;\n";
2602 pr " EXTEND (SP, n);\n";
2603 pr " for (i = 0; i < n; ++i)\n";
2604 pr " PUSHs (sv_2mortal (newSViv (r[i])));\n";
2612 pr " r = hivex_%s (%s);\n"
2613 name (String.concat ", " c_params);
2615 pr " if (r == NULL)\n";
2616 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2618 pr " for (n = 0; r[n] != NULL; ++n) /**/;\n";
2619 pr " EXTEND (SP, n);\n";
2620 pr " for (i = 0; i < n; ++i) {\n";
2621 pr " PUSHs (sv_2mortal (newSVpv (r[i], 0)));\n";
2622 pr " free (r[i]);\n";
2629 pr " size_t len;\n";
2630 pr " hive_type type;\n";
2632 pr " r = hivex_%s (%s, &type, &len);\n"
2633 name (String.concat ", " c_params);
2635 pr " if (r == -1)\n";
2636 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2638 pr " EXTEND (SP, 2);\n";
2639 pr " PUSHs (sv_2mortal (newSViv (type)));\n";
2640 pr " PUSHs (sv_2mortal (newSViv (len)));\n";
2645 pr " size_t len;\n";
2646 pr " hive_type type;\n";
2648 pr " r = hivex_%s (%s, &type, &len);\n"
2649 name (String.concat ", " c_params);
2651 pr " if (r == NULL)\n";
2652 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2654 pr " EXTEND (SP, 2);\n";
2655 pr " PUSHs (sv_2mortal (newSViv (type)));\n";
2656 pr " PUSHs (sv_2mortal (newSVpvn (r, len)));\n";
2664 pr " r = hivex_%s (%s);\n"
2665 name (String.concat ", " c_params);
2667 pr " if (r == -1 && errno != 0)\n";
2668 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2670 pr " RETVAL = newSViv (r);\n";
2679 pr " r = hivex_%s (%s);\n"
2680 name (String.concat ", " c_params);
2682 pr " if (r == -1 && errno != 0)\n";
2683 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2685 pr " RETVAL = my_newSVll (r);\n";
2693 and generate_python_c () =
2694 generate_header CStyle LGPLv2plus;
2697 #define PY_SSIZE_T_CLEAN 1
2700 #if PY_VERSION_HEX < 0x02050000
2701 typedef int Py_ssize_t;
2702 #define PY_SSIZE_T_MAX INT_MAX
2703 #define PY_SSIZE_T_MIN INT_MIN
2710 #include \"hivex.h\"
2712 #ifndef HAVE_PYCAPSULE_NEW
2720 get_handle (PyObject *obj)
2723 assert (obj != Py_None);
2724 #ifndef HAVE_PYCAPSULE_NEW
2725 return ((Pyhivex_Object *) obj)->h;
2727 return (hive_h *) PyCapsule_GetPointer(obj, \"hive_h\");
2732 put_handle (hive_h *h)
2735 #ifndef HAVE_PYCAPSULE_NEW
2737 PyCObject_FromVoidPtrAndDesc ((void *) h, (char *) \"hive_h\", NULL);
2739 return PyCapsule_New ((void *) h, \"hive_h\", NULL);
2743 /* This returns pointers into the Python objects, which should
2747 get_value (PyObject *v, hive_set_value *ret)
2751 obj = PyDict_GetItemString (v, \"key\");
2753 PyErr_SetString (PyExc_RuntimeError, \"no 'key' element in dictionary\");
2756 if (!PyString_Check (obj)) {
2757 PyErr_SetString (PyExc_RuntimeError, \"'key' element is not a string\");
2760 ret->key = PyString_AsString (obj);
2762 obj = PyDict_GetItemString (v, \"t\");
2764 PyErr_SetString (PyExc_RuntimeError, \"no 't' element in dictionary\");
2767 if (!PyInt_Check (obj)) {
2768 PyErr_SetString (PyExc_RuntimeError, \"'t' element is not an integer\");
2771 ret->t = PyInt_AsLong (obj);
2773 obj = PyDict_GetItemString (v, \"value\");
2775 PyErr_SetString (PyExc_RuntimeError, \"no 'value' element in dictionary\");
2778 if (!PyString_Check (obj)) {
2779 PyErr_SetString (PyExc_RuntimeError, \"'value' element is not a string\");
2782 ret->value = PyString_AsString (obj);
2783 ret->len = PyString_Size (obj);
2788 typedef struct py_set_values {
2790 hive_set_value *values;
2794 get_values (PyObject *v, py_set_values *ret)
2799 if (!PyList_Check (v)) {
2800 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
2804 slen = PyList_Size (v);
2806 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
2809 len = (size_t) slen;
2810 ret->nr_values = len;
2811 ret->values = malloc (len * sizeof (hive_set_value));
2813 PyErr_SetString (PyExc_RuntimeError, strerror (errno));
2817 for (i = 0; i < len; ++i) {
2818 if (get_value (PyList_GetItem (v, i), &(ret->values[i])) == -1) {
2828 put_string_list (char * const * const argv)
2833 for (argc = 0; argv[argc] != NULL; ++argc)
2836 list = PyList_New (argc);
2837 for (i = 0; i < argc; ++i)
2838 PyList_SetItem (list, i, PyString_FromString (argv[i]));
2844 free_strings (char **argv)
2848 for (argc = 0; argv[argc] != NULL; ++argc)
2853 /* Since hive_node_t is the same as hive_value_t this also works for values. */
2855 put_node_list (hive_node_h *nodes)
2860 for (argc = 0; nodes[argc] != 0; ++argc)
2863 list = PyList_New (argc);
2864 for (i = 0; i < argc; ++i)
2865 PyList_SetItem (list, i, PyLong_FromLongLong ((long) nodes[i]));
2871 put_len_type (size_t len, hive_type t)
2873 PyObject *r = PyTuple_New (2);
2874 PyTuple_SetItem (r, 0, PyInt_FromLong ((long) t));
2875 PyTuple_SetItem (r, 1, PyLong_FromLongLong ((long) len));
2880 put_val_type (char *val, size_t len, hive_type t)
2882 PyObject *r = PyTuple_New (2);
2883 PyTuple_SetItem (r, 0, PyInt_FromLong ((long) t));
2884 PyTuple_SetItem (r, 1, PyString_FromStringAndSize (val, len));
2890 (* Generate functions. *)
2892 fun (name, style, _, longdesc) ->
2893 pr "static PyObject *\n";
2894 pr "py_hivex_%s (PyObject *self, PyObject *args)\n" name;
2896 pr " PyObject *py_r;\n";
2899 match fst style with
2900 | RErr -> pr " int r;\n"; "-1"
2901 | RErrDispose -> pr " int r;\n"; "-1"
2902 | RHive -> pr " hive_h *r;\n"; "NULL"
2903 | RSize -> pr " size_t r;\n"; "0"
2904 | RNode -> pr " hive_node_h r;\n"; "0"
2907 pr " hive_node_h r;\n";
2909 | RNodeList -> pr " hive_node_h *r;\n"; "NULL"
2910 | RValue -> pr " hive_value_h r;\n"; "0"
2911 | RValueList -> pr " hive_value_h *r;\n"; "NULL"
2912 | RString -> pr " char *r;\n"; "NULL"
2913 | RStringList -> pr " char **r;\n"; "NULL"
2916 pr " size_t len;\n";
2917 pr " hive_type t;\n";
2921 pr " size_t len;\n";
2922 pr " hive_type t;\n";
2931 "-1 && errno != 0" in
2933 (* Call and arguments. *)
2936 | AUnusedFlags -> "0"
2937 | ASetValues -> "values.nr_values, values.values"
2938 | ASetValue -> "&val"
2939 | arg -> name_of_argt arg) (snd style) in
2941 match fst style with
2942 | RLenType | RLenTypeVal -> c_params @ ["&t"; "&len"]
2949 pr " PyObject *py_h;\n"
2954 | AStringNullable n ->
2958 | AUnusedFlags -> ()
2960 pr " py_set_values values;\n";
2961 pr " PyObject *py_values;\n"
2963 pr " hive_set_value val;\n";
2964 pr " PyObject *py_val;\n"
2969 (* Convert the required parameters. *)
2970 pr " if (!PyArg_ParseTuple (args, (char *) \"";
2980 | AStringNullable n ->
2984 | AUnusedFlags -> ()
2990 pr ":hivex_%s\"" name;
3000 | AStringNullable n ->
3004 | AUnusedFlags -> ()
3012 pr " return NULL;\n";
3014 (* Convert some Python argument types to C. *)
3018 pr " h = get_handle (py_h);\n"
3024 | AUnusedFlags -> ()
3026 pr " if (get_values (py_values, &values) == -1)\n";
3027 pr " return NULL;\n"
3029 pr " if (get_value (py_val, &val) == -1)\n";
3030 pr " return NULL;\n"
3033 (* Call the C function. *)
3034 pr " r = hivex_%s (%s);\n" name (String.concat ", " c_params);
3036 (* Free up arguments. *)
3039 | AHive | ANode _ | AValue _
3040 | AString _ | AStringNullable _
3041 | AOpenFlags | AUnusedFlags -> ()
3043 pr " free (values.values);\n"
3047 (* Check for errors from C library. *)
3048 pr " if (r == %s) {\n" error_code;
3049 pr " PyErr_SetString (PyExc_RuntimeError,\n";
3050 pr " strerror (errno));\n";
3051 pr " return NULL;\n";
3055 (* Convert return value to Python. *)
3056 (match fst style with
3059 pr " Py_INCREF (Py_None);\n";
3060 pr " py_r = Py_None;\n"
3062 pr " py_r = put_handle (r);\n"
3065 pr " py_r = PyLong_FromLongLong (r);\n"
3068 pr " py_r = PyLong_FromLongLong (r);\n";
3070 pr " Py_INCREF (Py_None);\n";
3071 pr " py_r = Py_None;\n";
3075 pr " py_r = put_node_list (r);\n";
3078 pr " py_r = PyLong_FromLongLong (r);\n"
3080 pr " py_r = PyString_FromString (r);\n";
3083 pr " py_r = put_string_list (r);\n";
3084 pr " free_strings (r);\n"
3086 pr " py_r = put_len_type (len, t);\n"
3088 pr " py_r = put_val_type (r, len, t);\n";
3091 pr " py_r = PyInt_FromLong ((long) r);\n"
3093 pr " py_r = PyLong_FromLongLong (r);\n"
3095 pr " return py_r;\n";
3100 (* Table of functions. *)
3101 pr "static PyMethodDef methods[] = {\n";
3103 fun (name, _, _, _) ->
3104 pr " { (char *) \"%s\", py_hivex_%s, METH_VARARGS, NULL },\n"
3107 pr " { NULL, NULL, 0, NULL }\n";
3111 (* Init function. *)
3114 initlibhivexmod (void)
3116 static int initialized = 0;
3118 if (initialized) return;
3119 Py_InitModule ((char *) \"libhivexmod\", methods);
3124 and generate_python_py () =
3125 generate_header HashStyle LGPLv2plus;
3128 u\"\"\"Python bindings for hivex
3131 h = hivex.Hivex (filename)
3133 The hivex module provides Python bindings to the hivex API for
3134 examining and modifying Windows Registry 'hive' files.
3136 Read the hivex(3) man page to find out how to use the API.
3142 \"\"\"Instances of this class are hivex API handles.\"\"\"
3144 def __init__ (self, filename";
3147 fun (_, flag, _) -> pr ", %s = False" (String.lowercase flag)
3151 \"\"\"Create a new hivex handle.\"\"\"
3156 fun (n, flag, description) ->
3157 pr " # %s\n" description;
3158 pr " if %s: flags += %d\n" (String.lowercase flag) n
3161 pr " self._o = libhivexmod.open (filename, flags)
3164 libhivexmod.close (self._o)
3169 fun (name, style, shortdesc, _) ->
3170 (* The close and open calls are handled specially above. *)
3171 if fst style <> RErrDispose && List.hd (snd style) = AHive then (
3172 let args = List.tl (snd style) in
3173 let args = List.filter (
3174 function AOpenFlags | AUnusedFlags -> false
3178 pr " def %s (self" name;
3179 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
3181 pr " u\"\"\"%s\"\"\"\n" shortdesc;
3182 pr " return libhivexmod.%s (self._o" name;
3187 | AHive -> assert false
3188 | ANode n | AValue n
3189 | AString n | AStringNullable n -> pr "%s" n
3191 | AUnusedFlags -> assert false
3192 | ASetValues -> pr "values"
3193 | ASetValue -> pr "val"
3200 and generate_ruby_c () =
3201 generate_header CStyle LGPLv2plus;
3210 #include \"hivex.h\"
3212 #include \"extconf.h\"
3214 /* For Ruby < 1.9 */
3216 #define RARRAY_LEN(r) (RARRAY((r))->len)
3219 static VALUE m_hivex; /* hivex module */
3220 static VALUE c_hivex; /* hive_h handle */
3221 static VALUE e_Error; /* used for all errors */
3224 ruby_hivex_free (void *hvp)
3233 get_value (VALUE valv, hive_set_value *val)
3235 VALUE key = rb_hash_lookup (valv, ID2SYM (rb_intern (\"key\")));
3236 VALUE type = rb_hash_lookup (valv, ID2SYM (rb_intern (\"type\")));
3237 VALUE value = rb_hash_lookup (valv, ID2SYM (rb_intern (\"value\")));
3239 val->key = StringValueCStr (key);
3240 val->t = NUM2ULL (type);
3241 val->len = RSTRING (value)->len;
3242 val->value = RSTRING (value)->ptr;
3245 static hive_set_value *
3246 get_values (VALUE valuesv, size_t *nr_values)
3249 hive_set_value *ret;
3251 *nr_values = RARRAY_LEN (valuesv);
3252 ret = malloc (sizeof (*ret) * *nr_values);
3256 for (i = 0; i < *nr_values; ++i) {
3257 VALUE v = rb_ary_entry (valuesv, i);
3258 get_value (v, &ret[i]);
3267 fun (name, (ret, args), shortdesc, longdesc) ->
3269 (* Generate rdoc. *)
3270 let doc = replace_str longdesc "C<hivex_" "C<h." in
3271 let doc = pod2text ~width:60 name doc in
3272 let doc = String.concat "\n * " doc in
3273 let doc = trim doc in
3277 | AHive :: args -> "h." ^ name, args
3278 | args -> "Hivex::" ^ name, args in
3279 let args = filter_map (
3281 | AUnusedFlags -> None
3282 | args -> Some (name_of_argt args)
3284 let args = String.concat ", " args in
3288 | RErr | RErrDispose -> "nil"
3289 | RHive -> "Hivex::Hivex"
3290 | RSize | RNode | RNodeNotFound -> "integer"
3291 | RNodeList -> "list"
3292 | RValue -> "integer"
3293 | RValueList -> "list"
3294 | RString -> "string"
3295 | RStringList -> "list"
3296 | RLenType -> "hash"
3297 | RLenTypeVal -> "hash"
3298 | RInt32 -> "integer"
3299 | RInt64 -> "integer" in
3310 * (For the C API documentation for this function, see
3311 * +hivex_%s+[http://libguestfs.org/hivex.3.html#hivex_%s]).
3313 " call args ret shortdesc doc name name in
3315 (* Generate the function. *)
3316 pr "static VALUE\n";
3317 pr "ruby_hivex_%s (" name;
3320 (* If the first argument is not AHive, then this is a module-level
3321 * function, and Ruby passes an implicit module argument which we
3322 * must ignore. Otherwise the first argument is the hive handle.
3326 | AHive :: args -> pr "VALUE hv"; args
3327 | args -> pr "VALUE modulev"; args in
3330 | AUnusedFlags -> ()
3332 pr ", VALUE %sv" (name_of_argt arg)
3342 pr " Data_Get_Struct (hv, hive_h, h);\n";
3344 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\",\n";
3345 pr " \"%s\");\n" name;
3347 pr " hive_node_h %s = NUM2ULL (%sv);\n" n n
3349 pr " hive_value_h %s = NUM2ULL (%sv);\n" n n
3351 pr " const char *%s = StringValueCStr (%sv);\n" n n;
3352 | AStringNullable n ->
3353 pr " const char *%s =\n" n;
3354 pr " !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n
3356 pr " int flags = 0;\n";
3359 pr " if (RTEST (rb_hash_lookup (flagsv, ID2SYM (rb_intern (\"%s\")))))\n"
3360 (String.lowercase flag);
3361 pr " flags += %d;\n" n
3363 | AUnusedFlags -> ()
3365 pr " size_t nr_values;\n";
3366 pr " hive_set_value *values;\n";
3367 pr " values = get_values (valuesv, &nr_values);\n"
3369 pr " hive_set_value val;\n";
3370 pr " get_value (valv, &val);\n"
3376 | RErr -> pr " int r;\n"; "-1"
3377 | RErrDispose -> pr " int r;\n"; "-1"
3378 | RHive -> pr " hive_h *r;\n"; "NULL"
3379 | RSize -> pr " size_t r;\n"; "0"
3380 | RNode -> pr " hive_node_h r;\n"; "0"
3383 pr " hive_node_h r;\n";
3385 | RNodeList -> pr " hive_node_h *r;\n"; "NULL"
3386 | RValue -> pr " hive_value_h r;\n"; "0"
3387 | RValueList -> pr " hive_value_h *r;\n"; "NULL"
3388 | RString -> pr " char *r;\n"; "NULL"
3389 | RStringList -> pr " char **r;\n"; "NULL"
3392 pr " size_t len;\n";
3393 pr " hive_type t;\n";
3397 pr " size_t len;\n";
3398 pr " hive_type t;\n";
3407 "-1 && errno != 0" in
3412 | ASetValues -> ["nr_values"; "values"]
3413 | ASetValue -> ["&val"]
3414 | AUnusedFlags -> ["0"]
3415 | arg -> [name_of_argt arg]) args in
3418 | RLenType | RLenTypeVal -> c_params @ [["&t"; "&len"]]
3420 let c_params = List.concat c_params in
3422 pr " r = hivex_%s (%s" name (List.hd c_params);
3423 List.iter (pr ", %s") (List.tl c_params);
3427 (* Dispose of the hive handle (even if hivex_close returns error). *)
3430 pr " /* So we don't double-free in the finalizer. */\n";
3431 pr " DATA_PTR (hv) = NULL;\n";
3444 | AUnusedFlags -> ()
3446 pr " free (values);\n"
3450 (* Check for errors from C library. *)
3451 pr " if (r == %s)\n" error_code;
3452 pr " rb_raise (e_Error, \"%%s\", strerror (errno));\n";
3456 | RErr | RErrDispose ->
3457 pr " return Qnil;\n"
3459 pr " return Data_Wrap_Struct (c_hivex, NULL, ruby_hivex_free, r);\n"
3464 pr " return ULL2NUM (r);\n"
3466 pr " return INT2NUM (r);\n"
3469 pr " return ULL2NUM (r);\n";
3471 pr " return Qnil;\n"
3474 pr " size_t i, len = 0;\n";
3475 pr " for (i = 0; r[i] != 0; ++i) len++;\n";
3476 pr " VALUE rv = rb_ary_new2 (len);\n";
3477 pr " for (i = 0; r[i] != 0; ++i)\n";
3478 pr " rb_ary_push (rv, ULL2NUM (r[i]));\n";
3482 pr " VALUE rv = rb_str_new2 (r);\n";
3486 pr " size_t i, len = 0;\n";
3487 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
3488 pr " VALUE rv = rb_ary_new2 (len);\n";
3489 pr " for (i = 0; r[i] != NULL; ++i) {\n";
3490 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
3491 pr " free (r[i]);\n";
3496 pr " VALUE rv = rb_hash_new ();\n";
3497 pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"len\")), INT2NUM (len));\n";
3498 pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"type\")), INT2NUM (t));\n";
3501 pr " VALUE rv = rb_hash_new ();\n";
3502 pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"len\")), INT2NUM (len));\n";
3503 pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"type\")), INT2NUM (t));\n";
3504 pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"value\")), rb_str_new (r, len));\n";
3514 /* Initialize the module. */
3517 m_hivex = rb_define_module (\"Hivex\");
3518 c_hivex = rb_define_class_under (m_hivex, \"Hivex\", rb_cObject);
3519 e_Error = rb_define_class_under (m_hivex, \"Error\", rb_eStandardError);
3521 /* XXX How to pass arguments? */
3523 #ifdef HAVE_RB_DEFINE_ALLOC_FUNC
3524 rb_define_alloc_func (c_hivex, ruby_hivex_open);
3532 fun (name, (_, args), _, _) ->
3533 let args = List.filter (
3535 | AUnusedFlags -> false
3538 let nr_args = List.length args in
3541 pr " rb_define_method (c_hivex, \"%s\",\n" name;
3542 pr " ruby_hivex_%s, %d);\n" name (nr_args-1)
3543 | args -> (* class function *)
3544 pr " rb_define_module_function (m_hivex, \"%s\",\n" name;
3545 pr " ruby_hivex_%s, %d);\n" name nr_args
3550 let output_to filename k =
3551 let filename_new = filename ^ ".new" in
3552 chan := open_out filename_new;
3555 chan := Pervasives.stdout;
3557 (* Is the new file different from the current file? *)
3558 if Sys.file_exists filename && files_equal filename filename_new then
3559 unlink filename_new (* same, so skip it *)
3561 (* different, overwrite old one *)
3562 (try chmod filename 0o644 with Unix_error _ -> ());
3563 rename filename_new filename;
3564 chmod filename 0o444;
3565 printf "written %s\n%!" filename;
3568 let perror msg = function
3569 | Unix_error (err, _, _) ->
3570 eprintf "%s: %s\n" msg (error_message err)
3572 eprintf "%s: %s\n" msg (Printexc.to_string exn)
3577 try openfile "configure.ac" [O_RDWR] 0
3579 | Unix_error (ENOENT, _, _) ->
3581 You are probably running this from the wrong directory.
3582 Run it from the top source directory using the command
3583 generator/generator.ml
3587 perror "open: configure.ac" exn;
3590 (* Acquire a lock so parallel builds won't try to run the generator
3591 * twice at the same time. Subsequent builds will wait for the first
3592 * one to finish. Note the lock is released implicitly when the
3595 (try lockf lock_fd F_LOCK 1
3597 perror "lock: configure.ac" exn;
3602 output_to "lib/hivex.h" generate_c_header;
3603 output_to "lib/hivex.pod" generate_c_pod;
3605 output_to "lib/hivex.syms" generate_linker_script;
3607 output_to "ocaml/hivex.mli" generate_ocaml_interface;
3608 output_to "ocaml/hivex.ml" generate_ocaml_implementation;
3609 output_to "ocaml/hivex_c.c" generate_ocaml_c;
3611 output_to "perl/lib/Win/Hivex.pm" generate_perl_pm;
3612 output_to "perl/Hivex.xs" generate_perl_xs;
3614 output_to "python/hivex.py" generate_python_py;
3615 output_to "python/hivex-py.c" generate_python_c;
3617 output_to "ruby/ext/hivex/_hivex.c" generate_ruby_c;
3619 (* Always generate this file last, and unconditionally. It's used
3620 * by the Makefile to know when we must re-run the generator.
3622 let chan = open_out "generator/stamp-generator" in
3626 printf "generated %d lines of code\n" !lines