3 * Copyright (C) 2009-2010 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 | RNode (* Returns hive_node_h or 0. *)
49 | RNodeNotFound (* See hivex_node_get_child. *)
50 | RNodeList (* Returns hive_node_h* or NULL. *)
51 | RValue (* Returns hive_value_h or 0. *)
52 | RValueList (* Returns hive_value_h* or NULL. *)
53 | RString (* Returns char* or NULL. *)
54 | RStringList (* Returns char** or NULL. *)
55 | RLenType (* See hivex_value_type. *)
56 | RLenTypeVal (* See hivex_value_value. *)
57 | RInt32 (* Returns int32. *)
58 | RInt64 (* Returns int64. *)
60 and args = argt list (* List of parameters. *)
62 and argt = (* Note, cannot be NULL/0 unless it
63 says so explicitly below. *)
65 | ANode of string (* hive_node_h *)
66 | AValue of string (* hive_value_h *)
67 | AString of string (* char* *)
68 | AStringNullable of string (* char* (can be NULL) *)
69 | AOpenFlags (* HIVEX_OPEN_* flags list. *)
70 | AUnusedFlags (* Flags arg that is always 0 *)
71 | ASetValues (* See hivex_node_set_values. *)
72 | ASetValue (* See hivex_node_set_value. *)
75 * https://secure.wikimedia.org/wikipedia/en/wiki/Windows_Registry#Keys_and_values
77 * It's unfortunate that in our original C binding we strayed away from
78 * the names that Windows uses (eg. REG_SZ for strings). We include
79 * both our names and the Windows names.
83 "Just a key without a value";
85 "A Windows string (encoding is unknown, but often UTF16-LE)";
86 2, "expand_string", "EXPAND_SZ",
87 "A Windows string that contains %env% (environment variable expansion)";
88 3, "binary", "BINARY",
91 "DWORD (32 bit integer), little endian";
92 5, "dword_be", "DWORD_BIG_ENDIAN",
93 "DWORD (32 bit integer), big endian";
95 "Symbolic link to another part of the registry tree";
96 7, "multiple_strings", "MULTI_SZ",
97 "Multiple Windows strings. See http://blogs.msdn.com/oldnewthing/archive/2009/10/08/9904646.aspx";
98 8, "resource_list", "RESOURCE_LIST",
100 9, "full_resource_description", "FULL_RESOURCE_DESCRIPTOR",
101 "Resource descriptor";
102 10, "resource_requirements_list", "RESOURCE_REQUIREMENTS_LIST",
103 "Resouce requirements list";
104 11, "qword", "QWORD",
105 "QWORD (64 bit integer), unspecified endianness but usually little endian"
107 let max_hive_type = 11
109 (* Open flags (bitmask passed to AOpenFlags) *)
111 1, "VERBOSE", "Verbose messages";
112 2, "DEBUG", "Debug messages";
113 4, "WRITE", "Enable writes to the hive";
118 "open", (RHive, [AString "filename"; AOpenFlags]),
121 Opens the hive named C<filename> for reading.
123 Flags is an ORed list of the open flags (or C<0> if you don't
124 want to pass any flags). These flags are defined:
128 =item HIVEX_OPEN_VERBOSE
132 =item HIVEX_OPEN_DEBUG
134 Very verbose messages, suitable for debugging problems in the library
137 This is also selected if the C<HIVEX_DEBUG> environment variable
140 =item HIVEX_OPEN_WRITE
142 Open the hive for writing. If omitted, the hive is read-only.
144 See L<hivex(3)/WRITING TO HIVE FILES>.
148 "close", (RErrDispose, [AHive]),
149 "close a hive handle",
151 Close a hive handle and free all associated resources.
153 Note that any uncommitted writes are I<not> committed by this call,
154 but instead are lost. See L<hivex(3)/WRITING TO HIVE FILES>.";
156 "root", (RNode, [AHive]),
157 "return the root node of the hive",
159 Return root node of the hive. All valid hives must contain a root node.";
161 "node_name", (RString, [AHive; ANode "node"]),
162 "return the name of the node",
164 Return the name of the node.
166 Note that the name of the root node is a dummy, such as
167 C<$$$PROTO.HIV> (other names are possible: it seems to depend on the
168 tool or program that created the hive in the first place). You can
169 only know the \"real\" name of the root node by knowing which registry
170 file this hive originally comes from, which is knowledge that is
171 outside the scope of this library.";
173 "node_children", (RNodeList, [AHive; ANode "node"]),
174 "return children of node",
176 Return an array of nodes which are the subkeys
177 (children) of C<node>.";
179 "node_get_child", (RNodeNotFound, [AHive; ANode "node"; AString "name"]),
180 "return named child of node",
182 Return the child of node with the name C<name>, if it exists.
184 The name is matched case insensitively.";
186 "node_parent", (RNode, [AHive; ANode "node"]),
187 "return the parent of node",
189 Return the parent of C<node>.
191 The parent pointer of the root node in registry files that we
192 have examined seems to be invalid, and so this function will
193 return an error if called on the root node.";
195 "node_values", (RValueList, [AHive; ANode "node"]),
196 "return (key, value) pairs attached to a node",
198 Return the array of (key, value) pairs attached to this node.";
200 "node_get_value", (RValue, [AHive; ANode "node"; AString "key"]),
201 "return named key at node",
203 Return the value attached to this node which has the name C<key>,
206 The key name is matched case insensitively.
208 Note that to get the default key, you should pass the empty
209 string C<\"\"> here. The default key is often written C<\"@\">, but
210 inside hives that has no meaning and won't give you the
213 "value_key", (RString, [AHive; AValue "val"]),
214 "return the key of a (key, value) pair",
216 Return the key (name) of a (key, value) pair. The name
217 is reencoded as UTF-8 and returned as a string.
219 The string should be freed by the caller when it is no longer needed.
221 Note that this function can return a zero-length string. In the
222 context of Windows Registries, this means that this value is the
223 default key for this node in the tree. This is usually written
226 "value_type", (RLenType, [AHive; AValue "val"]),
227 "return data length and data type of a value",
229 Return the data length and data type of the value in this (key, value)
230 pair. See also C<hivex_value_value> which returns all this
231 information, and the value itself. Also, C<hivex_value_*> functions
232 below which can be used to return the value in a more useful form when
233 you know the type in advance.";
235 "value_value", (RLenTypeVal, [AHive; AValue "val"]),
236 "return data length, data type and data of a value",
238 Return the value of this (key, value) pair. The value should
239 be interpreted according to its type (see C<hive_type>).";
241 "value_string", (RString, [AHive; AValue "val"]),
242 "return value as a string",
244 If this value is a string, return the string reencoded as UTF-8
245 (as a C string). This only works for values which have type
246 C<hive_t_string>, C<hive_t_expand_string> or C<hive_t_link>.";
248 "value_multiple_strings", (RStringList, [AHive; AValue "val"]),
249 "return value as multiple strings",
251 If this value is a multiple-string, return the strings reencoded
252 as UTF-8 (in C, as a NULL-terminated array of C strings, in other
253 language bindings, as a list of strings). This only
254 works for values which have type C<hive_t_multiple_strings>.";
256 "value_dword", (RInt32, [AHive; AValue "val"]),
257 "return value as a DWORD",
259 If this value is a DWORD (Windows int32), return it. This only works
260 for values which have type C<hive_t_dword> or C<hive_t_dword_be>.";
262 "value_qword", (RInt64, [AHive; AValue "val"]),
263 "return value as a QWORD",
265 If this value is a QWORD (Windows int64), return it. This only
266 works for values which have type C<hive_t_qword>.";
268 "commit", (RErr, [AHive; AStringNullable "filename"; AUnusedFlags]),
269 "commit (write) changes to file",
271 Commit (write) any changes which have been made.
273 C<filename> is the new file to write. If C<filename> is null/undefined
274 then we overwrite the original file (ie. the file name that was passed to
277 Note this does not close the hive handle. You can perform further
278 operations on the hive after committing, including making more
279 modifications. If you no longer wish to use the hive, then you
280 should close the handle after committing.";
282 "node_add_child", (RNode, [AHive; ANode "parent"; AString "name"]),
285 Add a new child node named C<name> to the existing node C<parent>.
286 The new child initially has no subnodes and contains no keys or
287 values. The sk-record (security descriptor) is inherited from
290 The parent must not have an existing child called C<name>, so if you
291 want to overwrite an existing child, call C<hivex_node_delete_child>
294 "node_delete_child", (RErr, [AHive; ANode "node"]),
297 Delete the node C<node>. All values at the node and all subnodes are
298 deleted (recursively). The C<node> handle and the handles of all
299 subnodes become invalid. You cannot delete the root node.";
301 "node_set_values", (RErr, [AHive; ANode "node"; ASetValues; AUnusedFlags]),
302 "set (key, value) pairs at a node",
304 This call can be used to set all the (key, value) pairs
307 C<node> is the node to modify.";
309 "node_set_value", (RErr, [AHive; ANode "node"; ASetValue; AUnusedFlags]),
310 "set a single (key, value) pair at a given node",
312 This call can be used to replace a single C<(key, value)> pair
313 stored in C<node>. If the key does not already exist, then a
314 new key is added. Key matching is case insensitive.
316 C<node> is the node to modify.";
319 (* Used to memoize the result of pod2text. *)
320 let pod2text_memo_filename = "generator/.pod2text.data"
321 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
323 let chan = open_in pod2text_memo_filename in
324 let v = input_value chan in
328 _ -> Hashtbl.create 13
329 let pod2text_memo_updated () =
330 let chan = open_out pod2text_memo_filename in
331 output_value chan pod2text_memo;
335 * Note we don't want to use any external OCaml libraries which
336 * makes this a bit harder than it should be.
338 module StringMap = Map.Make (String)
340 let failwithf fs = ksprintf failwith fs
342 let unique = let i = ref 0 in fun () -> incr i; !i
344 let replace_char s c1 c2 =
345 let s2 = String.copy s in
347 for i = 0 to String.length s2 - 1 do
348 if String.unsafe_get s2 i = c1 then (
349 String.unsafe_set s2 i c2;
353 if not !r then s else s2
357 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
359 let triml ?(test = isspace) str =
361 let n = ref (String.length str) in
362 while !n > 0 && test str.[!i]; do
367 else String.sub str !i !n
369 let trimr ?(test = isspace) str =
370 let n = ref (String.length str) in
371 while !n > 0 && test str.[!n-1]; do
374 if !n = String.length str then str
375 else String.sub str 0 !n
377 let trim ?(test = isspace) str =
378 trimr ~test (triml ~test str)
381 let len = String.length s in
382 let sublen = String.length sub in
384 if i <= len-sublen then (
387 if s.[i+j] = sub.[j] then loop2 (j+1)
393 if r = -1 then loop (i+1) else r
399 let rec replace_str s s1 s2 =
400 let len = String.length s in
401 let sublen = String.length s1 in
405 let s' = String.sub s 0 i in
406 let s'' = String.sub s (i+sublen) (len-i-sublen) in
407 s' ^ s2 ^ replace_str s'' s1 s2
410 let rec string_split sep str =
411 let len = String.length str in
412 let seplen = String.length sep in
413 let i = find str sep in
416 let s' = String.sub str 0 i in
417 let s'' = String.sub str (i+seplen) (len-i-seplen) in
418 s' :: string_split sep s''
421 let files_equal n1 n2 =
422 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
423 match Sys.command cmd with
426 | i -> failwithf "%s: failed with error code %d" cmd i
428 let rec filter_map f = function
432 | Some y -> y :: filter_map f xs
433 | None -> filter_map f xs
435 let rec find_map f = function
436 | [] -> raise Not_found
440 | None -> find_map f xs
443 let rec loop i = function
445 | x :: xs -> f i x; loop (i+1) xs
450 let rec loop i = function
452 | x :: xs -> let r = f i x in r :: loop (i+1) xs
456 let count_chars c str =
458 for i = 0 to String.length str - 1 do
459 if c = String.unsafe_get str i then incr count
463 let name_of_argt = function
465 | ANode n | AValue n | AString n | AStringNullable n -> n
466 | AOpenFlags | AUnusedFlags -> "flags"
467 | ASetValues -> "values"
470 (* Check function names etc. for consistency. *)
471 let check_functions () =
472 let contains_uppercase str =
473 let len = String.length str in
475 if i >= len then false
478 if c >= 'A' && c <= 'Z' then true
485 (* Check function names. *)
487 fun (name, _, _, _) ->
488 if String.length name >= 7 && String.sub name 0 7 = "hivex" then
489 failwithf "function name %s does not need 'hivex' prefix" name;
491 failwithf "function name is empty";
492 if name.[0] < 'a' || name.[0] > 'z' then
493 failwithf "function name %s must start with lowercase a-z" name;
494 if String.contains name '-' then
495 failwithf "function name %s should not contain '-', use '_' instead."
499 (* Check function parameter/return names. *)
501 fun (name, style, _, _) ->
502 let check_arg_ret_name n =
503 if contains_uppercase n then
504 failwithf "%s param/ret %s should not contain uppercase chars"
506 if String.contains n '-' || String.contains n '_' then
507 failwithf "%s param/ret %s should not contain '-' or '_'"
510 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;
511 if n = "int" || n = "char" || n = "short" || n = "long" then
512 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
513 if n = "i" || n = "n" then
514 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
515 if n = "argv" || n = "args" then
516 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
518 (* List Haskell, OCaml and C keywords here.
519 * http://www.haskell.org/haskellwiki/Keywords
520 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
521 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
522 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
523 * |perl -pe 's/(.+)/"$1";/'|fmt -70
524 * Omitting _-containing words, since they're handled above.
525 * Omitting the OCaml reserved word, "val", is ok,
526 * and saves us from renaming several parameters.
529 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
530 "char"; "class"; "const"; "constraint"; "continue"; "data";
531 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
532 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
533 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
534 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
535 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
537 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
538 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
539 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
540 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
541 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
542 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
543 "volatile"; "when"; "where"; "while";
545 if List.mem n reserved then
546 failwithf "%s has param/ret using reserved word %s" name n;
549 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
552 (* Check short descriptions. *)
554 fun (name, _, shortdesc, _) ->
555 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
556 failwithf "short description of %s should begin with lowercase." name;
557 let c = shortdesc.[String.length shortdesc-1] in
558 if c = '\n' || c = '.' then
559 failwithf "short description of %s should not end with . or \\n." name
562 (* Check long dscriptions. *)
564 fun (name, _, _, longdesc) ->
565 if longdesc.[String.length longdesc-1] = '\n' then
566 failwithf "long description of %s should not end with \\n." name
569 (* 'pr' prints to the current output file. *)
570 let chan = ref Pervasives.stdout
575 let i = count_chars '\n' str in
577 output_string !chan str
580 let copyright_years =
581 let this_year = 1900 + (localtime (time ())).tm_year in
582 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
584 (* Generate a header block in a number of standard styles. *)
586 | CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
588 type license = GPLv2plus | LGPLv2plus | GPLv2 | LGPLv2
590 let generate_header ?(extra_inputs = []) comment license =
591 let inputs = "generator/generator.ml" :: extra_inputs in
592 let c = match comment with
593 | CStyle -> pr "/* "; " *"
594 | CPlusPlusStyle -> pr "// "; "//"
595 | HashStyle -> pr "# "; "#"
596 | OCamlStyle -> pr "(* "; " *"
597 | HaskellStyle -> pr "{- "; " "
598 | PODCommentStyle -> pr "=begin comment\n\n "; "" in
599 pr "hivex generated file\n";
600 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
601 List.iter (pr "%s %s\n" c) inputs;
602 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
604 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
605 pr "%s Derived from code by Petter Nordahl-Hagen under a compatible license:\n" c;
606 pr "%s Copyright (c) 1997-2007 Petter Nordahl-Hagen.\n" c;
607 pr "%s Derived from code by Markus Stephany under a compatible license:\n" c;
608 pr "%s Copyright (c)2000-2004, Markus Stephany.\n" c;
612 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
613 pr "%s it under the terms of the GNU General Public License as published by\n" c;
614 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
615 pr "%s (at your option) any later version.\n" c;
617 pr "%s This program is distributed in the hope that it will be useful,\n" c;
618 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
619 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
620 pr "%s GNU General Public License for more details.\n" c;
622 pr "%s You should have received a copy of the GNU General Public License along\n" c;
623 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
624 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
627 pr "%s This library is free software; you can redistribute it and/or\n" c;
628 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
629 pr "%s License as published by the Free Software Foundation; either\n" c;
630 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
632 pr "%s This library is distributed in the hope that it will be useful,\n" c;
633 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
634 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
635 pr "%s Lesser General Public License for more details.\n" c;
637 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
638 pr "%s License along with this library; if not, write to the Free Software\n" c;
639 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
642 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
643 pr "%s it under the terms of the GNU General Public License as published by\n" c;
644 pr "%s the Free Software Foundation; version 2 of the License only.\n" c;
646 pr "%s This program is distributed in the hope that it will be useful,\n" c;
647 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
648 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
649 pr "%s GNU General Public License for more details.\n" c;
651 pr "%s You should have received a copy of the GNU General Public License along\n" c;
652 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
653 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
656 pr "%s This library is free software; you can redistribute it and/or\n" c;
657 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
658 pr "%s License as published by the Free Software Foundation;\n" c;
659 pr "%s version 2.1 of the License only.\n" c;
661 pr "%s This library is distributed in the hope that it will be useful,\n" c;
662 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
663 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
664 pr "%s Lesser General Public License for more details.\n" c;
666 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
667 pr "%s License along with this library; if not, write to the Free Software\n" c;
668 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
671 | CStyle -> pr " */\n"
674 | OCamlStyle -> pr " *)\n"
675 | HaskellStyle -> pr "-}\n"
676 | PODCommentStyle -> pr "\n=end comment\n"
680 (* Start of main code generation functions below this line. *)
682 let rec generate_c_header () =
683 generate_header CStyle LGPLv2;
695 /* NOTE: This API is documented in the man page hivex(3). */
698 typedef struct hive_h hive_h;
700 /* Nodes and values. */
701 typedef size_t hive_node_h;
702 typedef size_t hive_value_h;
706 # define HIVEX_NO_KEY ENOKEY
708 # define HIVEX_NO_KEY ENOENT
711 /* Pre-defined types. */
715 fun (t, old_style, new_style, description) ->
716 pr " /* %s */\n" description;
717 pr " hive_t_REG_%s,\n" new_style;
718 pr "#define hive_t_%s hive_t_REG_%s\n" old_style new_style;
724 typedef enum hive_type hive_type;
726 /* Bitmask of flags passed to hivex_open. */
729 fun (v, flag, description) ->
730 pr " /* %s */\n" description;
731 pr "#define HIVEX_OPEN_%-10s %d\n" flag v;
736 /* Array of (key, value) pairs passed to hivex_node_set_values. */
737 struct hive_set_value {
743 typedef struct hive_set_value hive_set_value;
747 pr "/* Functions. */\n";
749 (* Function declarations. *)
751 fun (shortname, style, _, _) ->
752 let name = "hivex_" ^ shortname in
753 generate_c_prototype ~extern:true name style
756 (* The visitor pattern. *)
758 /* Visit all nodes. This is specific to the C API and is not made
759 * available to other languages. This is because of the complexity
760 * of binding callbacks in other languages, but also because other
761 * languages make it much simpler to iterate over a tree.
763 struct hivex_visitor {
764 int (*node_start) (hive_h *, void *opaque, hive_node_h, const char *name);
765 int (*node_end) (hive_h *, void *opaque, hive_node_h, const char *name);
766 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);
767 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);
768 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);
769 int (*value_dword) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, int32_t);
770 int (*value_qword) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, int64_t);
771 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);
772 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);
773 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);
774 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);
777 #define HIVEX_VISIT_SKIP_BAD 1
779 extern int hivex_visit (hive_h *h, const struct hivex_visitor *visitor, size_t len, void *opaque, int flags);
780 extern int hivex_visit_node (hive_h *h, hive_node_h node, const struct hivex_visitor *visitor, size_t len, void *opaque, int flags);
784 (* Finish the header file. *)
790 #endif /* HIVEX_H_ */
793 and generate_c_prototype ?(extern = false) name style =
794 if extern then pr "extern ";
795 (match fst style with
797 | RErrDispose -> pr "int "
798 | RHive -> pr "hive_h *"
799 | RNode -> pr "hive_node_h "
800 | RNodeNotFound -> pr "hive_node_h "
801 | RNodeList -> pr "hive_node_h *"
802 | RValue -> pr "hive_value_h "
803 | RValueList -> pr "hive_value_h *"
804 | RString -> pr "char *"
805 | RStringList -> pr "char **"
806 | RLenType -> pr "int "
807 | RLenTypeVal -> pr "char *"
808 | RInt32 -> pr "int32_t "
809 | RInt64 -> pr "int64_t "
812 let comma = ref false in
815 if !comma then pr ", "; comma := true;
817 | AHive -> pr "hive_h *h"
818 | ANode n -> pr "hive_node_h %s" n
819 | AValue n -> pr "hive_value_h %s" n
820 | AString n | AStringNullable n -> pr "const char *%s" n
821 | AOpenFlags | AUnusedFlags -> pr "int flags"
822 | ASetValues -> pr "size_t nr_values, const hive_set_value *values"
823 | ASetValue -> pr "const hive_set_value *val"
825 (match fst style with
826 | RLenType | RLenTypeVal -> pr ", hive_type *t, size_t *len"
831 and generate_c_pod () =
832 generate_header PODCommentStyle GPLv2;
839 hivex - Windows Registry \"hive\" extraction library
847 fun (shortname, style, _, _) ->
848 let name = "hivex_" ^ shortname in
850 generate_c_prototype ~extern:false name style;
855 Link with I<-lhivex>.
859 Hivex is a library for extracting the contents of Windows Registry
860 \"hive\" files. It is designed to be secure against buggy or malicious
863 Unlike other tools in this area, it doesn't use the textual .REG
864 format, because parsing that is as much trouble as parsing the
865 original binary format. Instead it makes the file available
866 through a C API, and then wraps this API in higher level scripting
869 There is a separate program to export the hive as XML
870 (see L<hivexml(1)>), or to navigate the file (see L<hivexsh(1)>).
871 There is also a Perl script to export and merge the
872 file as a textual .REG (regedit) file, see L<hivexregedit(1)>.
874 If you just want to export or modify the Registry of a Windows
875 virtual machine, you should look at L<virt-win-reg(1)>.
877 Hivex is also comes with language bindings for
878 OCaml, Perl and Python.
884 This handle describes an open hive file.
886 =head2 C<hive_node_h>
888 This is a node handle, an integer but opaque outside the library.
889 Valid node handles cannot be 0. The library returns 0 in some
890 situations to indicate an error.
894 The enum below describes the possible types for the value(s)
895 stored at each node. Note that you should not trust the
896 type field in a Windows Registry, as it very often has no
897 relationship to reality. Some applications use their own
898 types. The encoding of strings is not specified. Some
899 programs store everything (including strings) in binary blobs.
904 fun (t, _, new_style, description) ->
905 pr " /* %s */\n" description;
906 pr " hive_t_REG_%s = %d,\n" new_style t
911 =head2 C<hive_value_h>
913 This is a value handle, an integer but opaque outside the library.
914 Valid value handles cannot be 0. The library returns 0 in some
915 situations to indicate an error.
917 =head2 C<hive_set_value>
919 The typedef C<hive_set_value> is used in conjunction with the
920 C<hivex_node_set_values> call described below.
922 struct hive_set_value {
923 char *key; /* key - a UTF-8 encoded ASCIIZ string */
924 hive_type t; /* type of value field */
925 size_t len; /* length of value field in bytes */
926 char *value; /* value field */
928 typedef struct hive_set_value hive_set_value;
930 To set the default value for a node, you have to pass C<key = \"\">.
932 Note that the C<value> field is just treated as a list of bytes, and
933 is stored directly in the hive. The caller has to ensure correct
934 encoding and endianness, for example converting dwords to little
937 The correct type and encoding for values depends on the node and key
938 in the registry, the version of Windows, and sometimes even changes
939 between versions of Windows for the same key. We don't document it
940 here. Often it's not documented at all.
946 fun (shortname, style, _, longdesc) ->
947 let name = "hivex_" ^ shortname in
948 pr "=head2 %s\n" name;
950 generate_c_prototype ~extern:false name style;
955 if List.mem AUnusedFlags (snd style) then
956 pr "The flags parameter is unused. Always pass 0.\n\n";
958 if List.mem ASetValues (snd style) then
959 pr "C<values> is an array of (key, value) pairs. There
960 should be C<nr_values> elements in this array.
962 Any existing values stored at the node are discarded, and their
963 C<hive_value_h> handles become invalid. Thus you can remove all
964 values stored at C<node> by passing C<nr_values = 0>.\n\n";
966 if List.mem ASetValue (snd style) then
967 pr "C<value> is a single (key, value) pair.
969 Existing C<hive_value_h> handles become invalid.\n\n";
971 (match fst style with
974 Returns 0 on success.
975 On error this returns -1 and sets errno.\n\n"
978 Returns 0 on success.
979 On error this returns -1 and sets errno.
981 This function frees the hive handle (even if it returns an error).
982 The hive handle must not be used again after calling this function.\n\n"
985 Returns a new hive handle.
986 On error this returns NULL and sets errno.\n\n"
989 Returns a node handle.
990 On error this returns 0 and sets errno.\n\n"
993 Returns a node handle.
994 If the node was not found, this returns 0 without setting errno.
995 On error this returns 0 and sets errno.\n\n"
998 Returns a 0-terminated array of nodes.
999 The array must be freed by the caller when it is no longer needed.
1000 On error this returns NULL and sets errno.\n\n"
1003 Returns a value handle.
1004 On error this returns 0 and sets errno.\n\n"
1007 Returns a 0-terminated array of values.
1008 The array must be freed by the caller when it is no longer needed.
1009 On error this returns NULL and sets errno.\n\n"
1013 The string must be freed by the caller when it is no longer needed.
1014 On error this returns NULL and sets errno.\n\n"
1017 Returns a NULL-terminated array of C strings.
1018 The strings and the array must all be freed by the caller when
1019 they are no longer needed.
1020 On error this returns NULL and sets errno.\n\n"
1023 Returns 0 on success.
1024 On error this returns -1 and sets errno.\n\n"
1027 The value is returned as an array of bytes (of length C<len>).
1028 The value must be freed by the caller when it is no longer needed.
1029 On error this returns NULL and sets errno.\n\n"
1030 | RInt32 | RInt64 -> ()
1035 =head1 WRITING TO HIVE FILES
1037 The hivex library supports making limited modifications to hive files.
1038 We have tried to implement this very conservatively in order to reduce
1039 the chance of corrupting your registry. However you should be careful
1040 and take back-ups, since Microsoft has never documented the hive
1041 format, and so it is possible there are nuances in the
1042 reverse-engineered format that we do not understand.
1044 To be able to modify a hive, you must pass the C<HIVEX_OPEN_WRITE>
1045 flag to C<hivex_open>, otherwise any write operation will return with
1048 The write operations shown below do not modify the on-disk file
1049 immediately. You must call C<hivex_commit> in order to write the
1050 changes to disk. If you call C<hivex_close> without committing then
1051 any writes are discarded.
1053 Hive files internally consist of a \"memory dump\" of binary blocks
1054 (like the C heap), and some of these blocks can be unused. The hivex
1055 library never reuses these unused blocks. Instead, to ensure
1056 robustness in the face of the partially understood on-disk format,
1057 hivex only allocates new blocks after the end of the file, and makes
1058 minimal modifications to existing structures in the file to point to
1059 these new blocks. This makes hivex slightly less disk-efficient than
1060 it could be, but disk is cheap, and registry modifications tend to be
1063 When deleting nodes, it is possible that this library may leave
1064 unreachable live blocks in the hive. This is because certain parts of
1065 the hive disk format such as security (sk) records and big data (db)
1066 records and classname fields are not well understood (and not
1067 documented at all) and we play it safe by not attempting to modify
1068 them. Apart from wasting a little bit of disk space, it is not
1069 thought that unreachable blocks are a problem.
1071 =head2 WRITE OPERATIONS WHICH ARE NOT SUPPORTED
1077 Changing the root node.
1081 Creating a new hive file from scratch. This is impossible at present
1082 because not all fields in the header are understood. In the hivex
1083 source tree is a file called C<images/minimal> which could be used as
1084 the basis for a new hive (but I<caveat emptor>).
1088 Modifying or deleting single values at a node.
1092 Modifying security key (sk) records or classnames.
1093 Previously we did not understand these records. However now they
1094 are well-understood and we could add support if it was required
1095 (but nothing much really uses them).
1099 =head1 VISITING ALL NODES
1101 The visitor pattern is useful if you want to visit all nodes
1102 in the tree or all nodes below a certain point in the tree.
1104 First you set up your own C<struct hivex_visitor> with your
1107 Each of these callback functions should return 0 on success or -1
1108 on error. If any callback returns -1, then the entire visit
1109 terminates immediately. If you don't need a callback function at
1110 all, set the function pointer to NULL.
1112 struct hivex_visitor {
1113 int (*node_start) (hive_h *, void *opaque, hive_node_h, const char *name);
1114 int (*node_end) (hive_h *, void *opaque, hive_node_h, const char *name);
1115 int (*value_string) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1116 hive_type t, size_t len, const char *key, const char *str);
1117 int (*value_multiple_strings) (hive_h *, void *opaque, hive_node_h,
1118 hive_value_h, hive_type t, size_t len, const char *key, char **argv);
1119 int (*value_string_invalid_utf16) (hive_h *, void *opaque, hive_node_h,
1120 hive_value_h, hive_type t, size_t len, const char *key,
1122 int (*value_dword) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1123 hive_type t, size_t len, const char *key, int32_t);
1124 int (*value_qword) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1125 hive_type t, size_t len, const char *key, int64_t);
1126 int (*value_binary) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1127 hive_type t, size_t len, const char *key, const char *value);
1128 int (*value_none) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1129 hive_type t, size_t len, const char *key, const char *value);
1130 int (*value_other) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1131 hive_type t, size_t len, const char *key, const char *value);
1132 /* If value_any callback is not NULL, then the other value_*
1133 * callbacks are not used, and value_any is called on all values.
1135 int (*value_any) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1136 hive_type t, size_t len, const char *key, const char *value);
1143 int hivex_visit (hive_h *h, const struct hivex_visitor *visitor, size_t len, void *opaque, int flags);
1145 Visit all the nodes recursively in the hive C<h>.
1147 C<visitor> should be a C<hivex_visitor> structure with callback
1148 fields filled in as required (unwanted callbacks can be set to
1149 NULL). C<len> must be the length of the 'visitor' struct (you
1150 should pass C<sizeof (struct hivex_visitor)> for this).
1152 This returns 0 if the whole recursive visit was completed
1153 successfully. On error this returns -1. If one of the callback
1154 functions returned an error than we don't touch errno. If the
1155 error was generated internally then we set errno.
1157 You can skip bad registry entries by setting C<flag> to
1158 C<HIVEX_VISIT_SKIP_BAD>. If this flag is not set, then a bad registry
1159 causes the function to return an error immediately.
1161 This function is robust if the registry contains cycles or
1162 pointers which are invalid or outside the registry. It detects
1163 these cases and returns an error.
1165 =item hivex_visit_node
1167 int hivex_visit_node (hive_h *h, hive_node_h node, const struct hivex_visitor *visitor, size_t len, void *opaque);
1169 Same as C<hivex_visit> but instead of starting out at the root, this
1174 =head1 THE STRUCTURE OF THE WINDOWS REGISTRY
1176 Note: To understand the relationship between hives and the common
1177 Windows Registry keys (like C<HKEY_LOCAL_MACHINE>) please see the
1178 Wikipedia page on the Windows Registry.
1180 The Windows Registry is split across various binary files, each
1181 file being known as a \"hive\". This library only handles a single
1182 hive file at a time.
1184 Hives are n-ary trees with a single root. Each node in the tree
1187 Each node in the tree (including non-leaf nodes) may have an
1188 arbitrary list of (key, value) pairs attached to it. It may
1189 be the case that one of these pairs has an empty key. This
1190 is referred to as the default key for the node.
1192 The (key, value) pairs are the place where the useful data is
1193 stored in the registry. The key is always a string (possibly the
1194 empty string for the default key). The value is a typed object
1195 (eg. string, int32, binary, etc.).
1197 =head2 RELATIONSHIP TO .REG FILES
1199 The hivex C library does not care about or deal with Windows .REG
1200 files. Instead we push this complexity up to the Perl
1201 L<Win::Hivex(3)> library and the Perl programs
1202 L<hivexregedit(1)> and L<virt-win-reg(1)>.
1203 Nevertheless it is useful to look at the relationship between the
1204 Registry and .REG files because they are so common.
1206 A .REG file is a textual representation of the registry, or part of the
1207 registry. The actual registry hives that Windows uses are binary
1208 files. There are a number of Windows and Linux tools that let you
1209 generate .REG files, or merge .REG files back into the registry hives.
1210 Notable amongst them is Microsoft's REGEDIT program (formerly known as
1213 A typical .REG file will contain many sections looking like this:
1215 [HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\Stack]
1216 \"@\"=\"Generic Stack\"
1217 \"TileInfo\"=\"prop:System.FileCount\"
1218 \"TilePath\"=str(2):\"%%systemroot%%\\\\system32\"
1219 \"ThumbnailCutoff\"=dword:00000000
1220 \"FriendlyTypeName\"=hex(2):40,00,25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,\\
1221 6f,00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,\\
1222 33,00,32,00,5c,00,73,00,65,00,61,00,72,00,63,00,68,00,66,00,\\
1223 6f,00,6c,00,64,00,65,00,72,00,2e,00,64,00,6c,00,6c,00,2c,00,\\
1224 2d,00,39,00,30,00,32,00,38,00,00,00,d8
1226 Taking this one piece at a time:
1228 [HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\Stack]
1230 This is the path to this node in the registry tree. The first part,
1231 C<HKEY_LOCAL_MACHINE\\SOFTWARE> means that this comes from a hive
1232 file called C<C:\\WINDOWS\\SYSTEM32\\CONFIG\\SOFTWARE>.
1233 C<\\Classes\\Stack> is the real path part,
1234 starting at the root node of the C<SOFTWARE> hive.
1236 Below the node name is a list of zero or more key-value pairs. Any
1237 interior or leaf node in the registry may have key-value pairs
1240 \"@\"=\"Generic Stack\"
1242 This is the \"default key\". In reality (ie. inside the binary hive)
1243 the key string is the empty string. In .REG files this is written as
1244 C<@> but this has no meaning either in the hives themselves or in this
1245 library. The value is a string (type 1 - see C<enum hive_type>
1248 \"TileInfo\"=\"prop:System.FileCount\"
1250 This is a regular (key, value) pair, with the value being a type 1
1251 string. Note that inside the binary file the string is likely to be
1252 UTF-16LE encoded. This library converts to and from UTF-8 strings
1253 transparently in some cases.
1255 \"TilePath\"=str(2):\"%%systemroot%%\\\\system32\"
1257 The value in this case has type 2 (expanded string) meaning that some
1258 %%...%% variables get expanded by Windows. (This library doesn't know
1259 or care about variable expansion).
1261 \"ThumbnailCutoff\"=dword:00000000
1263 The value in this case is a dword (type 4).
1265 \"FriendlyTypeName\"=hex(2):40,00,....
1267 This value is an expanded string (type 2) represented in the .REG file
1268 as a series of hex bytes. In this case the string appears to be a
1271 =head1 NOTE ON THE USE OF ERRNO
1273 Many functions in this library set errno to indicate errors. These
1274 are the values of errno you may encounter (this list is not
1281 Corrupt or unsupported Registry file format.
1289 Passed an invalid argument to the function.
1293 Followed a Registry pointer which goes outside
1294 the registry or outside a registry block.
1298 Registry contains cycles.
1302 Field in the registry out of range.
1306 Registry key already exists.
1310 Tried to write to a registry which is not opened for writing.
1314 =head1 ENVIRONMENT VARIABLES
1320 Setting HIVEX_DEBUG=1 will enable very verbose messages. This is
1321 useful for debugging problems with the library itself.
1334 L<http://libguestfs.org/>,
1337 L<http://en.wikipedia.org/wiki/Windows_Registry>.
1341 Richard W.M. Jones (C<rjones at redhat dot com>)
1345 Copyright (C) 2009-2010 Red Hat Inc.
1347 Derived from code by Petter Nordahl-Hagen under a compatible license:
1348 Copyright (C) 1997-2007 Petter Nordahl-Hagen.
1350 Derived from code by Markus Stephany under a compatible license:
1351 Copyright (C) 2000-2004 Markus Stephany.
1353 This library is free software; you can redistribute it and/or
1354 modify it under the terms of the GNU Lesser General Public
1355 License as published by the Free Software Foundation;
1356 version 2.1 of the License only.
1358 This library is distributed in the hope that it will be useful,
1359 but WITHOUT ANY WARRANTY; without even the implied warranty of
1360 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1361 Lesser General Public License for more details.
1364 (* Generate the linker script which controls the visibility of
1365 * symbols in the public ABI and ensures no other symbols get
1366 * exported accidentally.
1368 and generate_linker_script () =
1369 generate_header HashStyle GPLv2plus;
1377 List.map (fun (name, _, _, _) -> "hivex_" ^ name)
1379 let globals = List.sort compare (globals @ functions) in
1383 List.iter (pr " %s;\n") globals;
1390 and generate_ocaml_interface () =
1391 generate_header OCamlStyle LGPLv2plus;
1395 (** A [hive_h] hive file handle. *)
1399 (** Nodes and values. *)
1401 exception Error of string * Unix.error * string
1402 (** Error raised by a function.
1404 The first parameter is the name of the function which raised the error.
1405 The second parameter is the errno (see the [Unix] module). The third
1406 parameter is a human-readable string corresponding to the errno.
1408 See hivex(3) for a partial list of interesting errno values that
1409 can be generated by the library. *)
1410 exception Handle_closed of string
1411 (** This exception is raised if you call a function on a closed handle. *)
1417 fun (t, _, new_style, description) ->
1419 pr " | REG_%s (** %s *)\n" new_style description
1423 | REG_UNKNOWN of int32 (** unknown type *)
1424 (** Hive type field. *)
1430 fun (v, flag, description) ->
1431 assert (1 lsl i = v);
1432 pr " | OPEN_%s (** %s *)\n" flag description
1436 (** Open flags for {!open_file} call. *)
1443 (** (key, value) pair passed (as an array) to {!node_set_values}. *)
1447 fun (name, style, shortdesc, _) ->
1449 generate_ocaml_prototype name style;
1450 pr "(** %s *)\n" shortdesc
1453 and generate_ocaml_implementation () =
1454 generate_header OCamlStyle LGPLv2plus;
1461 exception Error of string * Unix.error * string
1462 exception Handle_closed of string
1464 (* Give the exceptions names, so they can be raised from the C code. *)
1466 Callback.register_exception \"ocaml_hivex_error\"
1467 (Error (\"\", Unix.EUNKNOWNERR 0, \"\"));
1468 Callback.register_exception \"ocaml_hivex_closed\" (Handle_closed \"\")
1474 fun (t, _, new_style, _) ->
1476 pr " | REG_%s\n" new_style
1480 | REG_UNKNOWN of int32
1486 fun (v, flag, description) ->
1487 assert (1 lsl i = v);
1488 pr " | OPEN_%s (** %s *)\n" flag description
1502 fun (name, style, _, _) ->
1503 generate_ocaml_prototype ~is_external:true name style
1506 and generate_ocaml_prototype ?(is_external = false) name style =
1507 let ocaml_name = if name = "open" then "open_file" else name in
1509 if is_external then pr "external " else pr "val ";
1510 pr "%s : " ocaml_name;
1513 | AHive -> pr "t -> "
1514 | ANode _ -> pr "node -> "
1515 | AValue _ -> pr "value -> "
1516 | AString _ -> pr "string -> "
1517 | AStringNullable _ -> pr "string option -> "
1518 | AOpenFlags -> pr "open_flag list -> "
1519 | AUnusedFlags -> ()
1520 | ASetValues -> pr "set_value array -> "
1521 | ASetValue -> pr "set_value -> "
1523 (match fst style with
1524 | RErr -> pr "unit" (* all errors are turned into exceptions *)
1525 | RErrDispose -> pr "unit"
1527 | RNode -> pr "node"
1528 | RNodeNotFound -> pr "node"
1529 | RNodeList -> pr "node array"
1530 | RValue -> pr "value"
1531 | RValueList -> pr "value array"
1532 | RString -> pr "string"
1533 | RStringList -> pr "string array"
1534 | RLenType -> pr "hive_type * int"
1535 | RLenTypeVal -> pr "hive_type * string"
1536 | RInt32 -> pr "int32"
1537 | RInt64 -> pr "int64"
1540 pr " = \"ocaml_hivex_%s\"" name;
1543 and generate_ocaml_c () =
1544 generate_header CStyle LGPLv2plus;
1555 #include <caml/config.h>
1556 #include <caml/alloc.h>
1557 #include <caml/callback.h>
1558 #include <caml/custom.h>
1559 #include <caml/fail.h>
1560 #include <caml/memory.h>
1561 #include <caml/mlvalues.h>
1562 #include <caml/signals.h>
1564 #ifdef HAVE_CAML_UNIXSUPPORT_H
1565 #include <caml/unixsupport.h>
1567 extern value unix_error_of_code (int errcode);
1570 #ifndef HAVE_CAML_RAISE_WITH_ARGS
1572 caml_raise_with_args (value tag, int nargs, value args[])
1575 CAMLxparamN (args, nargs);
1579 bucket = caml_alloc_small (1 + nargs, 0);
1580 Field(bucket, 0) = tag;
1581 for (i = 0; i < nargs; i++) Field(bucket, 1 + i) = args[i];
1589 #define Hiveh_val(v) (*((hive_h **)Data_custom_val(v)))
1590 static value Val_hiveh (hive_h *);
1591 static int HiveOpenFlags_val (value);
1592 static hive_set_value *HiveSetValue_val (value);
1593 static hive_set_value *HiveSetValues_val (value);
1594 static hive_type HiveType_val (value);
1595 static value Val_hive_type (hive_type);
1596 static value copy_int_array (size_t *);
1597 static value copy_type_len (size_t, hive_type);
1598 static value copy_type_value (const char *, size_t, hive_type);
1599 static void raise_error (const char *) Noreturn;
1600 static void raise_closed (const char *) Noreturn;
1606 fun (name, style, _, _) ->
1607 pr "/* Automatically generated wrapper for function\n";
1608 pr " * "; generate_ocaml_prototype name style;
1614 | ASetValues -> ["nrvalues"; "values"]
1615 | AUnusedFlags -> ["0"]
1616 | arg -> [name_of_argt arg]) (snd style) in
1618 match fst style with
1619 | RLenType | RLenTypeVal -> c_params @ [["&t"; "&len"]]
1621 let c_params = List.concat c_params in
1624 filter_map (function
1625 | AUnusedFlags -> None
1626 | arg -> Some (name_of_argt arg ^ "v")) (snd style) in
1628 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
1629 pr "CAMLprim value ocaml_hivex_%s (value %s" name (List.hd params);
1630 List.iter (pr ", value %s") (List.tl params); pr ");\n";
1633 pr "CAMLprim value\n";
1634 pr "ocaml_hivex_%s (value %s" name (List.hd params);
1635 List.iter (pr ", value %s") (List.tl params);
1639 pr " CAMLparam%d (%s);\n"
1640 (List.length params) (String.concat ", " params);
1641 pr " CAMLlocal1 (rv);\n";
1647 pr " hive_h *h = Hiveh_val (hv);\n";
1648 pr " if (h == NULL)\n";
1649 pr " raise_closed (\"%s\");\n" name
1651 pr " hive_node_h %s = Int_val (%sv);\n" n n
1653 pr " hive_value_h %s = Int_val (%sv);\n" n n
1655 pr " const char *%s = String_val (%sv);\n" n n
1656 | AStringNullable n ->
1657 pr " const char *%s =\n" n;
1658 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
1661 pr " int flags = HiveOpenFlags_val (flagsv);\n"
1662 | AUnusedFlags -> ()
1664 pr " int nrvalues = Wosize_val (valuesv);\n";
1665 pr " hive_set_value *values = HiveSetValues_val (valuesv);\n"
1667 pr " hive_set_value *val = HiveSetValue_val (valv);\n"
1672 match fst style with
1673 | RErr -> pr " int r;\n"; "-1"
1674 | RErrDispose -> pr " int r;\n"; "-1"
1675 | RHive -> pr " hive_h *r;\n"; "NULL"
1676 | RNode -> pr " hive_node_h r;\n"; "0"
1679 pr " hive_node_h r;\n";
1681 | RNodeList -> pr " hive_node_h *r;\n"; "NULL"
1682 | RValue -> pr " hive_value_h r;\n"; "0"
1683 | RValueList -> pr " hive_value_h *r;\n"; "NULL"
1684 | RString -> pr " char *r;\n"; "NULL"
1685 | RStringList -> pr " char **r;\n"; "NULL"
1688 pr " size_t len;\n";
1689 pr " hive_type t;\n";
1693 pr " size_t len;\n";
1694 pr " hive_type t;\n";
1703 "-1 && errno != 0" in
1705 (* The libguestfs OCaml bindings call enter_blocking_section
1706 * here. However I don't think that is safe, because we are
1707 * holding pointers to caml strings during the call, and these
1708 * could be moved or freed by other threads. In any case, there
1709 * is very little reason to enter_blocking_section for any hivex
1710 * call, so don't do it. XXX
1712 (*pr " caml_enter_blocking_section ();\n";*)
1713 pr " r = hivex_%s (%s" name (List.hd c_params);
1714 List.iter (pr ", %s") (List.tl c_params);
1716 (*pr " caml_leave_blocking_section ();\n";*)
1719 (* Dispose of the hive handle (even if hivex_close returns error). *)
1720 (match fst style with
1722 pr " /* So we don't double-free in the finalizer. */\n";
1723 pr " Hiveh_val (hv) = NULL;\n";
1730 | AHive | ANode _ | AValue _ | AString _ | AStringNullable _
1731 | AOpenFlags | AUnusedFlags -> ()
1733 pr " free (values);\n";
1736 pr " free (val);\n";
1740 (* Check for errors. *)
1741 pr " if (r == %s)\n" error_code;
1742 pr " raise_error (\"%s\");\n" name;
1745 (match fst style with
1746 | RErr -> pr " rv = Val_unit;\n"
1747 | RErrDispose -> pr " rv = Val_unit;\n"
1748 | RHive -> pr " rv = Val_hiveh (r);\n"
1749 | RNode -> pr " rv = Val_int (r);\n"
1751 pr " if (r == 0)\n";
1752 pr " caml_raise_not_found ();\n";
1754 pr " rv = Val_int (r);\n"
1756 pr " rv = copy_int_array (r);\n";
1758 | RValue -> pr " rv = Val_int (r);\n"
1760 pr " rv = copy_int_array (r);\n";
1763 pr " rv = caml_copy_string (r);\n";
1766 pr " rv = caml_copy_string_array ((const char **) r);\n";
1767 pr " for (int i = 0; r[i] != NULL; ++i) free (r[i]);\n";
1769 | RLenType -> pr " rv = copy_type_len (len, t);\n"
1771 pr " rv = copy_type_value (r, len, t);\n";
1773 | RInt32 -> pr " rv = caml_copy_int32 (r);\n"
1774 | RInt64 -> pr " rv = caml_copy_int32 (r);\n"
1777 pr " CAMLreturn (rv);\n";
1785 HiveOpenFlags_val (value v)
1790 while (v != Val_int (0)) {
1792 flags |= 1 << Int_val (v2);
1799 static hive_set_value *
1800 HiveSetValue_val (value v)
1802 hive_set_value *val = malloc (sizeof (hive_set_value));
1804 val->key = String_val (Field (v, 0));
1805 val->t = HiveType_val (Field (v, 1));
1806 val->len = caml_string_length (Field (v, 2));
1807 val->value = String_val (Field (v, 2));
1812 static hive_set_value *
1813 HiveSetValues_val (value v)
1815 size_t nr_values = Wosize_val (v);
1816 hive_set_value *values = malloc (nr_values * sizeof (hive_set_value));
1820 for (i = 0; i < nr_values; ++i) {
1822 values[i].key = String_val (Field (v2, 0));
1823 values[i].t = HiveType_val (Field (v2, 1));
1824 values[i].len = caml_string_length (Field (v2, 2));
1825 values[i].value = String_val (Field (v2, 2));
1832 HiveType_val (value v)
1835 return Int_val (v); /* REG_NONE etc. */
1837 return Int32_val (Field (v, 0)); /* REG_UNKNOWN of int32 */
1841 Val_hive_type (hive_type t)
1847 CAMLreturn (Val_int (t));
1849 rv = caml_alloc (1, 0); /* REG_UNKNOWN of int32 */
1850 v = caml_copy_int32 (t);
1851 caml_modify (&Field (rv, 0), v);
1857 copy_int_array (size_t *xs)
1863 for (nr = 0; xs[nr] != 0; ++nr)
1866 CAMLreturn (Atom (0));
1868 rv = caml_alloc (nr, 0);
1869 for (i = 0; i < nr; ++i) {
1870 v = Val_int (xs[i]);
1871 Store_field (rv, i, v); /* Safe because v is not a block. */
1878 copy_type_len (size_t len, hive_type t)
1883 rv = caml_alloc (2, 0);
1884 v = Val_hive_type (t);
1885 Store_field (rv, 0, v);
1887 Store_field (rv, 1, len);
1892 copy_type_value (const char *r, size_t len, hive_type t)
1897 rv = caml_alloc (2, 0);
1898 v = Val_hive_type (t);
1899 Store_field (rv, 0, v);
1900 v = caml_alloc_string (len);
1901 memcpy (String_val (v), r, len);
1902 caml_modify (&Field (rv, 1), v);
1906 /* Raise exceptions. */
1908 raise_error (const char *function)
1910 /* Save errno early in case it gets trashed. */
1914 CAMLlocal3 (v1, v2, v3);
1916 v1 = caml_copy_string (function);
1917 v2 = unix_error_of_code (err);
1918 v3 = caml_copy_string (strerror (err));
1919 value vvv[] = { v1, v2, v3 };
1920 caml_raise_with_args (*caml_named_value (\"ocaml_hivex_error\"), 3, vvv);
1926 raise_closed (const char *function)
1931 v = caml_copy_string (function);
1932 caml_raise_with_arg (*caml_named_value (\"ocaml_hivex_closed\"), v);
1937 /* Allocate handles and deal with finalization. */
1939 hivex_finalize (value hv)
1941 hive_h *h = Hiveh_val (hv);
1942 if (h) hivex_close (h);
1945 static struct custom_operations hivex_custom_operations = {
1946 (char *) \"hivex_custom_operations\",
1948 custom_compare_default,
1949 custom_hash_default,
1950 custom_serialize_default,
1951 custom_deserialize_default
1955 Val_hiveh (hive_h *h)
1960 rv = caml_alloc_custom (&hivex_custom_operations,
1961 sizeof (hive_h *), 0, 1);
1968 and generate_perl_pm () =
1969 generate_header HashStyle LGPLv2plus;
1976 Win::Hivex - Perl bindings for reading and writing Windows Registry hive files
1982 $h = Win::Hivex->open ('SOFTWARE');
1983 $root_node = $h->root ();
1984 print $h->node_name ($root_node);
1988 The C<Win::Hivex> module provides a Perl XS binding to the
1989 L<hivex(3)> API for reading and writing Windows Registry binary
1994 All errors turn into calls to C<croak> (see L<Carp(3)>).
2008 XSLoader::load ('Win::Hivex');
2012 $h = Win::Hivex->open ($filename,";
2016 pr "\n [%s => 1,]" (String.lowercase flag)
2021 Open a Windows Registry binary hive file.
2023 The C<verbose> and C<debug> flags enable different levels of
2026 The C<write> flag is required if you will be modifying the
2027 hive file (see L<hivex(3)/WRITING TO HIVE FILES>).
2029 This function returns a hive handle. The hive handle is
2030 closed automatically when its reference count drops to 0.
2036 my $class = ref ($proto) || $proto;
2037 my $filename = shift;
2044 fun (n, flag, description) ->
2045 pr " # %s\n" description;
2046 pr " $flags += %d if $flags{%s};\n" n (String.lowercase flag)
2051 my $self = Win::Hivex::_open ($filename, $flags);
2052 bless $self, $class;
2059 fun (name, style, _, longdesc) ->
2060 (* The close call isn't explicit in Perl: handles are closed
2061 * when their reference count drops to 0.
2063 * The open call is coded specially in Perl.
2065 * Therefore we don't generate prototypes for these two calls:
2067 if fst style <> RErrDispose && List.hd (snd style) = AHive then (
2068 let longdesc = replace_str longdesc "C<hivex_" "C<" in
2069 pr "=item %s\n\n " name;
2070 generate_perl_prototype name style;
2072 pr "%s\n\n" longdesc;
2074 (match fst style with
2086 This returns a node handle.\n\n"
2089 This returns a node handle, or C<undef> if the node was not found.\n\n"
2092 This returns a list of node handles.\n\n"
2095 This returns a value handle.\n\n"
2098 This returns a list of value handles.\n\n"
2101 if List.mem ASetValues (snd style) then
2102 pr "C<@values> is an array of (keys, value) pairs.
2103 Each element should be a hashref containing C<key>, C<t> (type)
2106 Any existing values stored at the node are discarded, and their
2107 C<value> handles become invalid. Thus you can remove all
2108 values stored at C<node> by passing C<@values = []>.\n\n"
2121 Copyright (C) %s Red Hat Inc.
2125 Please see the file COPYING.LIB for the full license.
2131 L<http://libguestfs.org>,
2137 and generate_perl_prototype name style =
2139 (match fst style with
2142 | RHive -> pr "$h = "
2144 | RNodeNotFound -> pr "$node = "
2145 | RNodeList -> pr "@nodes = "
2146 | RValue -> pr "$value = "
2147 | RValueList -> pr "@values = "
2148 | RString -> pr "$string = "
2149 | RStringList -> pr "@strings = "
2150 | RLenType -> pr "($type, $len) = "
2151 | RLenTypeVal -> pr "($type, $data) = "
2152 | RInt32 -> pr "$int32 = "
2153 | RInt64 -> pr "$int64 = "
2156 let args = List.tl (snd style) in
2158 (* AUnusedFlags is dropped in the bindings. *)
2159 let args = List.filter ((<>) AUnusedFlags) args in
2163 let comma = ref false in
2166 if !comma then pr ", "; comma := true;
2171 | AString n -> pr "$%s" n
2172 | AStringNullable n -> pr "[$%s|undef]" n
2173 | AOpenFlags -> pr "[flags]"
2174 | AUnusedFlags -> assert false
2175 | ASetValues -> pr "\\@values"
2176 | ASetValue -> pr "$val"
2181 and generate_perl_xs () =
2182 generate_header CStyle LGPLv2plus;
2185 #include \"EXTERN.h\"
2193 #define PRId64 \"lld\"
2197 my_newSVll(long long val) {
2198 #ifdef USE_64_BIT_ALL
2199 return newSViv(val);
2203 len = snprintf(buf, 100, \"%%\" PRId64, val);
2204 return newSVpv(buf, len);
2209 #define PRIu64 \"llu\"
2214 my_newSVull(unsigned long long val) {
2215 #ifdef USE_64_BIT_ALL
2216 return newSVuv(val);
2220 len = snprintf(buf, 100, \"%%\" PRIu64, val);
2221 return newSVpv(buf, len);
2227 /* http://www.perlmonks.org/?node_id=680842 */
2229 XS_unpack_charPtrPtr (SV *arg) {
2234 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
2235 croak (\"array reference expected\");
2237 av = (AV *)SvRV (arg);
2238 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
2240 croak (\"malloc failed\");
2242 for (i = 0; i <= av_len (av); i++) {
2243 SV **elem = av_fetch (av, i, 0);
2245 if (!elem || !*elem)
2246 croak (\"missing element in list\");
2248 ret[i] = SvPV_nolen (*elem);
2257 /* Handle set_values parameter. */
2258 typedef struct pl_set_values {
2260 hive_set_value *values;
2263 static pl_set_values
2264 unpack_pl_set_values (SV *sv)
2270 if (!sv || !SvOK (sv) || !SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV)
2271 croak (\"array reference expected\");
2273 av = (AV *)SvRV(sv);
2274 ret.nr_values = av_len (av) + 1;
2275 ret.values = malloc (ret.nr_values * sizeof (hive_set_value));
2277 croak (\"malloc failed\");
2279 for (i = 0; i <= av_len (av); i++) {
2280 SV **hvp = av_fetch (av, i, 0);
2282 if (!hvp || !*hvp || !SvROK (*hvp) || SvTYPE (SvRV (*hvp)) != SVt_PVHV)
2283 croak (\"missing element in list or not a hash ref\");
2285 HV *hv = (HV *)SvRV(*hvp);
2288 svp = hv_fetch (hv, \"key\", 3, 0);
2290 croak (\"missing 'key' in hash\");
2291 ret.values[i].key = SvPV_nolen (*svp);
2293 svp = hv_fetch (hv, \"t\", 1, 0);
2295 croak (\"missing 't' in hash\");
2296 ret.values[i].t = SvIV (*svp);
2298 svp = hv_fetch (hv, \"value\", 5, 0);
2300 croak (\"missing 'value' in hash\");
2301 ret.values[i].value = SvPV (*svp, ret.values[i].len);
2307 static hive_set_value *
2308 unpack_set_value (SV *sv)
2310 hive_set_value *ret;
2312 if (!sv || !SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVHV)
2313 croak (\"not a hash ref\");
2315 ret = malloc (sizeof (hive_set_value));
2317 croak (\"malloc failed\");
2319 HV *hv = (HV *)SvRV(sv);
2322 svp = hv_fetch (hv, \"key\", 3, 0);
2324 croak (\"missing 'key' in hash\");
2325 ret->key = SvPV_nolen (*svp);
2327 svp = hv_fetch (hv, \"t\", 1, 0);
2329 croak (\"missing 't' in hash\");
2330 ret->t = SvIV (*svp);
2332 svp = hv_fetch (hv, \"value\", 5, 0);
2334 croak (\"missing 'value' in hash\");
2335 ret->value = SvPV (*svp, ret->len);
2340 MODULE = Win::Hivex PACKAGE = Win::Hivex
2345 _open (filename, flags)
2349 RETVAL = hivex_open (filename, flags);
2351 croak (\"hivex_open: %%s: %%s\", filename, strerror (errno));
2359 if (hivex_close (h) == -1)
2360 croak (\"hivex_close: %%s\", strerror (errno));
2365 fun (name, style, _, longdesc) ->
2366 (* The close and open calls are handled specially above. *)
2367 if fst style <> RErrDispose && List.hd (snd style) = AHive then (
2368 (match fst style with
2369 | RErr -> pr "void\n"
2370 | RErrDispose -> failwith "perl bindings cannot handle a call which disposes of the handle"
2371 | RHive -> failwith "perl bindings cannot handle a call which returns a handle"
2375 | RString -> pr "SV *\n"
2380 | RLenTypeVal -> pr "void\n"
2381 | RInt32 -> pr "SV *\n"
2382 | RInt64 -> pr "SV *\n"
2385 (* Call and arguments. *)
2387 filter_map (function
2388 | AUnusedFlags -> None
2389 | arg -> Some (name_of_argt arg)) (snd style) in
2393 | AUnusedFlags -> "0"
2394 | ASetValues -> "values.nr_values, values.values"
2395 | arg -> name_of_argt arg) (snd style) in
2397 pr "%s (%s)\n" name (String.concat ", " perl_params);
2408 | AStringNullable n ->
2409 (* http://www.perlmonks.org/?node_id=554277 *)
2410 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n i i
2413 | AUnusedFlags -> ()
2415 pr " pl_set_values values = unpack_pl_set_values (ST(%d));\n" i
2417 pr " hive_set_value *val = unpack_set_value (ST(%d));\n" i
2424 pr " free (values.values);\n"
2427 | AHive | ANode _ | AValue _ | AString _ | AStringNullable _
2428 | AOpenFlags | AUnusedFlags -> ()
2433 (match fst style with
2438 pr " r = hivex_%s (%s);\n"
2439 name (String.concat ", " c_params);
2441 pr " if (r == -1)\n";
2442 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2445 | RErrDispose -> assert false
2446 | RHive -> assert false
2451 pr " /* hive_node_h = hive_value_h = size_t so we cheat\n";
2452 pr " here to simplify the generator */\n";
2455 pr " r = hivex_%s (%s);\n"
2456 name (String.concat ", " c_params);
2458 pr " if (r == 0)\n";
2459 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2461 pr " RETVAL = newSViv (r);\n";
2467 pr " hive_node_h r;\n";
2470 pr " r = hivex_%s (%s);\n"
2471 name (String.concat ", " c_params);
2473 pr " if (r == 0 && errno != 0)\n";
2474 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2476 pr " if (r == 0)\n";
2477 pr " RETVAL = &PL_sv_undef;\n";
2479 pr " RETVAL = newSViv (r);\n";
2487 pr " r = hivex_%s (%s);\n"
2488 name (String.concat ", " c_params);
2490 pr " if (r == NULL)\n";
2491 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2493 pr " RETVAL = newSVpv (r, 0);\n";
2504 pr " r = hivex_%s (%s);\n"
2505 name (String.concat ", " c_params);
2507 pr " if (r == NULL)\n";
2508 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2510 pr " for (n = 0; r[n] != 0; ++n) /**/;\n";
2511 pr " EXTEND (SP, n);\n";
2512 pr " for (i = 0; i < n; ++i)\n";
2513 pr " PUSHs (sv_2mortal (newSViv (r[i])));\n";
2521 pr " r = hivex_%s (%s);\n"
2522 name (String.concat ", " c_params);
2524 pr " if (r == NULL)\n";
2525 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2527 pr " for (n = 0; r[n] != NULL; ++n) /**/;\n";
2528 pr " EXTEND (SP, n);\n";
2529 pr " for (i = 0; i < n; ++i) {\n";
2530 pr " PUSHs (sv_2mortal (newSVpv (r[i], 0)));\n";
2531 pr " free (r[i]);\n";
2538 pr " size_t len;\n";
2539 pr " hive_type type;\n";
2541 pr " r = hivex_%s (%s, &type, &len);\n"
2542 name (String.concat ", " c_params);
2544 pr " if (r == -1)\n";
2545 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2547 pr " EXTEND (SP, 2);\n";
2548 pr " PUSHs (sv_2mortal (newSViv (type)));\n";
2549 pr " PUSHs (sv_2mortal (newSViv (len)));\n";
2554 pr " size_t len;\n";
2555 pr " hive_type type;\n";
2557 pr " r = hivex_%s (%s, &type, &len);\n"
2558 name (String.concat ", " c_params);
2560 pr " if (r == NULL)\n";
2561 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2563 pr " EXTEND (SP, 2);\n";
2564 pr " PUSHs (sv_2mortal (newSViv (type)));\n";
2565 pr " PUSHs (sv_2mortal (newSVpvn (r, len)));\n";
2573 pr " r = hivex_%s (%s);\n"
2574 name (String.concat ", " c_params);
2576 pr " if (r == -1 && errno != 0)\n";
2577 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2579 pr " RETVAL = newSViv (r);\n";
2588 pr " r = hivex_%s (%s);\n"
2589 name (String.concat ", " c_params);
2591 pr " if (r == -1 && errno != 0)\n";
2592 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2594 pr " RETVAL = my_newSVll (r);\n";
2602 and generate_python_c () =
2603 generate_header CStyle LGPLv2plus;
2606 #define PY_SSIZE_T_CLEAN 1
2609 #if PY_VERSION_HEX < 0x02050000
2610 typedef int Py_ssize_t;
2611 #define PY_SSIZE_T_MAX INT_MAX
2612 #define PY_SSIZE_T_MIN INT_MIN
2619 #include \"hivex.h\"
2621 #ifndef HAVE_PYCAPSULE_NEW
2629 get_handle (PyObject *obj)
2632 assert (obj != Py_None);
2633 #ifndef HAVE_PYCAPSULE_NEW
2634 return ((Pyhivex_Object *) obj)->h;
2636 return (hive_h *) PyCapsule_GetPointer(obj, \"hive_h\");
2641 put_handle (hive_h *h)
2644 #ifndef HAVE_PYCAPSULE_NEW
2646 PyCObject_FromVoidPtrAndDesc ((void *) h, (char *) \"hive_h\", NULL);
2648 return PyCapsule_New ((void *) h, \"hive_h\", NULL);
2652 /* This returns pointers into the Python objects, which should
2656 get_value (PyObject *v, hive_set_value *ret)
2660 obj = PyDict_GetItemString (v, \"key\");
2662 PyErr_SetString (PyExc_RuntimeError, \"no 'key' element in dictionary\");
2665 if (!PyString_Check (obj)) {
2666 PyErr_SetString (PyExc_RuntimeError, \"'key' element is not a string\");
2669 ret->key = PyString_AsString (obj);
2671 obj = PyDict_GetItemString (v, \"t\");
2673 PyErr_SetString (PyExc_RuntimeError, \"no 't' element in dictionary\");
2676 if (!PyInt_Check (obj)) {
2677 PyErr_SetString (PyExc_RuntimeError, \"'t' element is not an integer\");
2680 ret->t = PyInt_AsLong (obj);
2682 obj = PyDict_GetItemString (v, \"value\");
2684 PyErr_SetString (PyExc_RuntimeError, \"no 'value' element in dictionary\");
2687 if (!PyString_Check (obj)) {
2688 PyErr_SetString (PyExc_RuntimeError, \"'value' element is not a string\");
2691 ret->value = PyString_AsString (obj);
2692 ret->len = PyString_Size (obj);
2697 typedef struct py_set_values {
2699 hive_set_value *values;
2703 get_values (PyObject *v, py_set_values *ret)
2708 if (!PyList_Check (v)) {
2709 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
2713 slen = PyList_Size (v);
2715 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
2718 len = (size_t) slen;
2719 ret->nr_values = len;
2720 ret->values = malloc (len * sizeof (hive_set_value));
2722 PyErr_SetString (PyExc_RuntimeError, strerror (errno));
2726 for (i = 0; i < len; ++i) {
2727 if (get_value (PyList_GetItem (v, i), &(ret->values[i])) == -1) {
2737 put_string_list (char * const * const argv)
2742 for (argc = 0; argv[argc] != NULL; ++argc)
2745 list = PyList_New (argc);
2746 for (i = 0; i < argc; ++i)
2747 PyList_SetItem (list, i, PyString_FromString (argv[i]));
2753 free_strings (char **argv)
2757 for (argc = 0; argv[argc] != NULL; ++argc)
2762 /* Since hive_node_t is the same as hive_value_t this also works for values. */
2764 put_node_list (hive_node_h *nodes)
2769 for (argc = 0; nodes[argc] != 0; ++argc)
2772 list = PyList_New (argc);
2773 for (i = 0; i < argc; ++i)
2774 PyList_SetItem (list, i, PyLong_FromLongLong ((long) nodes[i]));
2780 put_len_type (size_t len, hive_type t)
2782 PyObject *r = PyTuple_New (2);
2783 PyTuple_SetItem (r, 0, PyInt_FromLong ((long) t));
2784 PyTuple_SetItem (r, 1, PyLong_FromLongLong ((long) len));
2789 put_val_type (char *val, size_t len, hive_type t)
2791 PyObject *r = PyTuple_New (2);
2792 PyTuple_SetItem (r, 0, PyInt_FromLong ((long) t));
2793 PyTuple_SetItem (r, 1, PyString_FromStringAndSize (val, len));
2799 (* Generate functions. *)
2801 fun (name, style, _, longdesc) ->
2802 pr "static PyObject *\n";
2803 pr "py_hivex_%s (PyObject *self, PyObject *args)\n" name;
2805 pr " PyObject *py_r;\n";
2808 match fst style with
2809 | RErr -> pr " int r;\n"; "-1"
2810 | RErrDispose -> pr " int r;\n"; "-1"
2811 | RHive -> pr " hive_h *r;\n"; "NULL"
2812 | RNode -> pr " hive_node_h r;\n"; "0"
2815 pr " hive_node_h r;\n";
2817 | RNodeList -> pr " hive_node_h *r;\n"; "NULL"
2818 | RValue -> pr " hive_value_h r;\n"; "0"
2819 | RValueList -> pr " hive_value_h *r;\n"; "NULL"
2820 | RString -> pr " char *r;\n"; "NULL"
2821 | RStringList -> pr " char **r;\n"; "NULL"
2824 pr " size_t len;\n";
2825 pr " hive_type t;\n";
2829 pr " size_t len;\n";
2830 pr " hive_type t;\n";
2839 "-1 && errno != 0" in
2841 (* Call and arguments. *)
2844 | AUnusedFlags -> "0"
2845 | ASetValues -> "values.nr_values, values.values"
2846 | ASetValue -> "&val"
2847 | arg -> name_of_argt arg) (snd style) in
2849 match fst style with
2850 | RLenType | RLenTypeVal -> c_params @ ["&t"; "&len"]
2857 pr " PyObject *py_h;\n"
2862 | AStringNullable n ->
2866 | AUnusedFlags -> ()
2868 pr " py_set_values values;\n";
2869 pr " PyObject *py_values;\n"
2871 pr " hive_set_value val;\n";
2872 pr " PyObject *py_val;\n"
2877 (* Convert the required parameters. *)
2878 pr " if (!PyArg_ParseTuple (args, (char *) \"";
2888 | AStringNullable n ->
2892 | AUnusedFlags -> ()
2898 pr ":hivex_%s\"" name;
2908 | AStringNullable n ->
2912 | AUnusedFlags -> ()
2920 pr " return NULL;\n";
2922 (* Convert some Python argument types to C. *)
2926 pr " h = get_handle (py_h);\n"
2932 | AUnusedFlags -> ()
2934 pr " if (get_values (py_values, &values) == -1)\n";
2935 pr " return NULL;\n"
2937 pr " if (get_value (py_val, &val) == -1)\n";
2938 pr " return NULL;\n"
2941 (* Call the C function. *)
2942 pr " r = hivex_%s (%s);\n" name (String.concat ", " c_params);
2944 (* Free up arguments. *)
2947 | AHive | ANode _ | AValue _
2948 | AString _ | AStringNullable _
2949 | AOpenFlags | AUnusedFlags -> ()
2951 pr " free (values.values);\n"
2955 (* Check for errors from C library. *)
2956 pr " if (r == %s) {\n" error_code;
2957 pr " PyErr_SetString (PyExc_RuntimeError,\n";
2958 pr " strerror (errno));\n";
2959 pr " return NULL;\n";
2963 (* Convert return value to Python. *)
2964 (match fst style with
2967 pr " Py_INCREF (Py_None);\n";
2968 pr " py_r = Py_None;\n"
2970 pr " py_r = put_handle (r);\n"
2972 pr " py_r = PyLong_FromLongLong (r);\n"
2975 pr " py_r = PyLong_FromLongLong (r);\n";
2977 pr " Py_INCREF (Py_None);\n";
2978 pr " py_r = Py_None;\n";
2982 pr " py_r = put_node_list (r);\n";
2985 pr " py_r = PyLong_FromLongLong (r);\n"
2987 pr " py_r = PyString_FromString (r);\n";
2990 pr " py_r = put_string_list (r);\n";
2991 pr " free_strings (r);\n"
2993 pr " py_r = put_len_type (len, t);\n"
2995 pr " py_r = put_val_type (r, len, t);\n";
2998 pr " py_r = PyInt_FromLong ((long) r);\n"
3000 pr " py_r = PyLong_FromLongLong (r);\n"
3002 pr " return py_r;\n";
3007 (* Table of functions. *)
3008 pr "static PyMethodDef methods[] = {\n";
3010 fun (name, _, _, _) ->
3011 pr " { (char *) \"%s\", py_hivex_%s, METH_VARARGS, NULL },\n"
3014 pr " { NULL, NULL, 0, NULL }\n";
3018 (* Init function. *)
3021 initlibhivexmod (void)
3023 static int initialized = 0;
3025 if (initialized) return;
3026 Py_InitModule ((char *) \"libhivexmod\", methods);
3031 and generate_python_py () =
3032 generate_header HashStyle LGPLv2plus;
3035 u\"\"\"Python bindings for hivex
3038 h = hivex.Hivex (filename)
3040 The hivex module provides Python bindings to the hivex API for
3041 examining and modifying Windows Registry 'hive' files.
3043 Read the hivex(3) man page to find out how to use the API.
3049 \"\"\"Instances of this class are hivex API handles.\"\"\"
3051 def __init__ (self, filename";
3054 fun (_, flag, _) -> pr ", %s = False" (String.lowercase flag)
3058 \"\"\"Create a new hivex handle.\"\"\"
3063 fun (n, flag, description) ->
3064 pr " # %s\n" description;
3065 pr " if %s: flags += %d\n" (String.lowercase flag) n
3068 pr " self._o = libhivexmod.open (filename, flags)
3071 libhivexmod.close (self._o)
3076 fun (name, style, shortdesc, _) ->
3077 (* The close and open calls are handled specially above. *)
3078 if fst style <> RErrDispose && List.hd (snd style) = AHive then (
3079 let args = List.tl (snd style) in
3080 let args = List.filter (
3081 function AOpenFlags | AUnusedFlags -> false
3085 pr " def %s (self" name;
3086 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
3088 pr " u\"\"\"%s\"\"\"\n" shortdesc;
3089 pr " return libhivexmod.%s (self._o" name;
3094 | AHive -> assert false
3095 | ANode n | AValue n
3096 | AString n | AStringNullable n -> pr "%s" n
3098 | AUnusedFlags -> assert false
3099 | ASetValues -> pr "values"
3100 | ASetValue -> pr "val"
3107 let output_to filename k =
3108 let filename_new = filename ^ ".new" in
3109 chan := open_out filename_new;
3112 chan := Pervasives.stdout;
3114 (* Is the new file different from the current file? *)
3115 if Sys.file_exists filename && files_equal filename filename_new then
3116 unlink filename_new (* same, so skip it *)
3118 (* different, overwrite old one *)
3119 (try chmod filename 0o644 with Unix_error _ -> ());
3120 rename filename_new filename;
3121 chmod filename 0o444;
3122 printf "written %s\n%!" filename;
3125 let perror msg = function
3126 | Unix_error (err, _, _) ->
3127 eprintf "%s: %s\n" msg (error_message err)
3129 eprintf "%s: %s\n" msg (Printexc.to_string exn)
3134 try openfile "configure.ac" [O_RDWR] 0
3136 | Unix_error (ENOENT, _, _) ->
3138 You are probably running this from the wrong directory.
3139 Run it from the top source directory using the command
3140 generator/generator.ml
3144 perror "open: configure.ac" exn;
3147 (* Acquire a lock so parallel builds won't try to run the generator
3148 * twice at the same time. Subsequent builds will wait for the first
3149 * one to finish. Note the lock is released implicitly when the
3152 (try lockf lock_fd F_LOCK 1
3154 perror "lock: configure.ac" exn;
3159 output_to "lib/hivex.h" generate_c_header;
3160 output_to "lib/hivex.pod" generate_c_pod;
3162 output_to "lib/hivex.syms" generate_linker_script;
3164 output_to "ocaml/hivex.mli" generate_ocaml_interface;
3165 output_to "ocaml/hivex.ml" generate_ocaml_implementation;
3166 output_to "ocaml/hivex_c.c" generate_ocaml_c;
3168 output_to "perl/lib/Win/Hivex.pm" generate_perl_pm;
3169 output_to "perl/Hivex.xs" generate_perl_xs;
3171 output_to "python/hivex.py" generate_python_py;
3172 output_to "python/hivex-py.c" generate_python_c;
3174 (* Always generate this file last, and unconditionally. It's used
3175 * by the Makefile to know when we must re-run the generator.
3177 let chan = open_out "generator/stamp-generator" in
3181 printf "generated %d lines of code\n" !lines