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 "value_value", (RLenTypeVal, [AHive; AValue "val"]),
266 "return data length, data type and data of a value",
268 Return the value of this (key, value) pair. The value should
269 be interpreted according to its type (see C<hive_type>).";
271 "value_string", (RString, [AHive; AValue "val"]),
272 "return value as a string",
274 If this value is a string, return the string reencoded as UTF-8
275 (as a C string). This only works for values which have type
276 C<hive_t_string>, C<hive_t_expand_string> or C<hive_t_link>.";
278 "value_multiple_strings", (RStringList, [AHive; AValue "val"]),
279 "return value as multiple strings",
281 If this value is a multiple-string, return the strings reencoded
282 as UTF-8 (in C, as a NULL-terminated array of C strings, in other
283 language bindings, as a list of strings). This only
284 works for values which have type C<hive_t_multiple_strings>.";
286 "value_dword", (RInt32, [AHive; AValue "val"]),
287 "return value as a DWORD",
289 If this value is a DWORD (Windows int32), return it. This only works
290 for values which have type C<hive_t_dword> or C<hive_t_dword_be>.";
292 "value_qword", (RInt64, [AHive; AValue "val"]),
293 "return value as a QWORD",
295 If this value is a QWORD (Windows int64), return it. This only
296 works for values which have type C<hive_t_qword>.";
298 "commit", (RErr, [AHive; AStringNullable "filename"; AUnusedFlags]),
299 "commit (write) changes to file",
301 Commit (write) any changes which have been made.
303 C<filename> is the new file to write. If C<filename> is null/undefined
304 then we overwrite the original file (ie. the file name that was passed to
307 Note this does not close the hive handle. You can perform further
308 operations on the hive after committing, including making more
309 modifications. If you no longer wish to use the hive, then you
310 should close the handle after committing.";
312 "node_add_child", (RNode, [AHive; ANode "parent"; AString "name"]),
315 Add a new child node named C<name> to the existing node C<parent>.
316 The new child initially has no subnodes and contains no keys or
317 values. The sk-record (security descriptor) is inherited from
320 The parent must not have an existing child called C<name>, so if you
321 want to overwrite an existing child, call C<hivex_node_delete_child>
324 "node_delete_child", (RErr, [AHive; ANode "node"]),
327 Delete the node C<node>. All values at the node and all subnodes are
328 deleted (recursively). The C<node> handle and the handles of all
329 subnodes become invalid. You cannot delete the root node.";
331 "node_set_values", (RErr, [AHive; ANode "node"; ASetValues; AUnusedFlags]),
332 "set (key, value) pairs at a node",
334 This call can be used to set all the (key, value) pairs
337 C<node> is the node to modify.";
339 "node_set_value", (RErr, [AHive; ANode "node"; ASetValue; AUnusedFlags]),
340 "set a single (key, value) pair at a given node",
342 This call can be used to replace a single C<(key, value)> pair
343 stored in C<node>. If the key does not already exist, then a
344 new key is added. Key matching is case insensitive.
346 C<node> is the node to modify.";
350 * Note we don't want to use any external OCaml libraries which
351 * makes this a bit harder than it should be.
353 module StringMap = Map.Make (String)
355 let failwithf fs = ksprintf failwith fs
357 let unique = let i = ref 0 in fun () -> incr i; !i
359 let replace_char s c1 c2 =
360 let s2 = String.copy s in
362 for i = 0 to String.length s2 - 1 do
363 if String.unsafe_get s2 i = c1 then (
364 String.unsafe_set s2 i c2;
368 if not !r then s else s2
372 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
374 let triml ?(test = isspace) str =
376 let n = ref (String.length str) in
377 while !n > 0 && test str.[!i]; do
382 else String.sub str !i !n
384 let trimr ?(test = isspace) str =
385 let n = ref (String.length str) in
386 while !n > 0 && test str.[!n-1]; do
389 if !n = String.length str then str
390 else String.sub str 0 !n
392 let trim ?(test = isspace) str =
393 trimr ~test (triml ~test str)
395 (* Used to memoize the result of pod2text. *)
396 let pod2text_memo_filename = "generator/.pod2text.data.version.2"
397 let pod2text_memo : ((int option * bool * bool * string * string), string list) Hashtbl.t =
399 let chan = open_in pod2text_memo_filename in
400 let v = input_value chan in
404 _ -> Hashtbl.create 13
405 let pod2text_memo_updated () =
406 let chan = open_out pod2text_memo_filename in
407 output_value chan pod2text_memo;
410 (* Useful if you need the longdesc POD text as plain text. Returns a
413 * Because this is very slow (the slowest part of autogeneration),
414 * we memoize the results.
416 let pod2text ?width ?(trim = true) ?(discard = true) name longdesc =
417 let key = width, trim, discard, name, longdesc in
418 try Hashtbl.find pod2text_memo key
420 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
421 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
426 sprintf "pod2text -w %d %s" width (Filename.quote filename)
428 sprintf "pod2text %s" (Filename.quote filename) in
429 let chan = open_process_in cmd in
430 let lines = ref [] in
432 let line = input_line chan in
433 if i = 1 && discard then (* discard the first line of output *)
436 let line = if trim then triml line else line in
437 lines := line :: !lines;
440 let lines = try loop 1 with End_of_file -> List.rev !lines in
442 (match close_process_in chan with
445 failwithf "pod2text: process exited with non-zero status (%d)" i
446 | WSIGNALED i | WSTOPPED i ->
447 failwithf "pod2text: process signalled or stopped by signal %d" i
449 Hashtbl.add pod2text_memo key lines;
450 pod2text_memo_updated ();
454 let len = String.length s in
455 let sublen = String.length sub in
457 if i <= len-sublen then (
460 if s.[i+j] = sub.[j] then loop2 (j+1)
466 if r = -1 then loop (i+1) else r
472 let rec replace_str s s1 s2 =
473 let len = String.length s in
474 let sublen = String.length s1 in
478 let s' = String.sub s 0 i in
479 let s'' = String.sub s (i+sublen) (len-i-sublen) in
480 s' ^ s2 ^ replace_str s'' s1 s2
483 let rec string_split sep str =
484 let len = String.length str in
485 let seplen = String.length sep in
486 let i = find str sep in
489 let s' = String.sub str 0 i in
490 let s'' = String.sub str (i+seplen) (len-i-seplen) in
491 s' :: string_split sep s''
494 let files_equal n1 n2 =
495 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
496 match Sys.command cmd with
499 | i -> failwithf "%s: failed with error code %d" cmd i
501 let rec filter_map f = function
505 | Some y -> y :: filter_map f xs
506 | None -> filter_map f xs
508 let rec find_map f = function
509 | [] -> raise Not_found
513 | None -> find_map f xs
516 let rec loop i = function
518 | x :: xs -> f i x; loop (i+1) xs
523 let rec loop i = function
525 | x :: xs -> let r = f i x in r :: loop (i+1) xs
529 let count_chars c str =
531 for i = 0 to String.length str - 1 do
532 if c = String.unsafe_get str i then incr count
536 let name_of_argt = function
538 | ANode n | AValue n | AString n | AStringNullable n -> n
539 | AOpenFlags | AUnusedFlags -> "flags"
540 | ASetValues -> "values"
543 (* Check function names etc. for consistency. *)
544 let check_functions () =
545 let contains_uppercase str =
546 let len = String.length str in
548 if i >= len then false
551 if c >= 'A' && c <= 'Z' then true
558 (* Check function names. *)
560 fun (name, _, _, _) ->
561 if String.length name >= 7 && String.sub name 0 7 = "hivex" then
562 failwithf "function name %s does not need 'hivex' prefix" name;
564 failwithf "function name is empty";
565 if name.[0] < 'a' || name.[0] > 'z' then
566 failwithf "function name %s must start with lowercase a-z" name;
567 if String.contains name '-' then
568 failwithf "function name %s should not contain '-', use '_' instead."
572 (* Check function parameter/return names. *)
574 fun (name, style, _, _) ->
575 let check_arg_ret_name n =
576 if contains_uppercase n then
577 failwithf "%s param/ret %s should not contain uppercase chars"
579 if String.contains n '-' || String.contains n '_' then
580 failwithf "%s param/ret %s should not contain '-' or '_'"
583 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;
584 if n = "int" || n = "char" || n = "short" || n = "long" then
585 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
586 if n = "i" || n = "n" then
587 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
588 if n = "argv" || n = "args" then
589 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
591 (* List Haskell, OCaml and C keywords here.
592 * http://www.haskell.org/haskellwiki/Keywords
593 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
594 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
595 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
596 * |perl -pe 's/(.+)/"$1";/'|fmt -70
597 * Omitting _-containing words, since they're handled above.
598 * Omitting the OCaml reserved word, "val", is ok,
599 * and saves us from renaming several parameters.
602 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
603 "char"; "class"; "const"; "constraint"; "continue"; "data";
604 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
605 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
606 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
607 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
608 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
610 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
611 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
612 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
613 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
614 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
615 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
616 "volatile"; "when"; "where"; "while";
618 if List.mem n reserved then
619 failwithf "%s has param/ret using reserved word %s" name n;
622 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
625 (* Check short descriptions. *)
627 fun (name, _, shortdesc, _) ->
628 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
629 failwithf "short description of %s should begin with lowercase." name;
630 let c = shortdesc.[String.length shortdesc-1] in
631 if c = '\n' || c = '.' then
632 failwithf "short description of %s should not end with . or \\n." name
635 (* Check long dscriptions. *)
637 fun (name, _, _, longdesc) ->
638 if longdesc.[String.length longdesc-1] = '\n' then
639 failwithf "long description of %s should not end with \\n." name
642 (* 'pr' prints to the current output file. *)
643 let chan = ref Pervasives.stdout
648 let i = count_chars '\n' str in
650 output_string !chan str
653 let copyright_years =
654 let this_year = 1900 + (localtime (time ())).tm_year in
655 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
657 (* Generate a header block in a number of standard styles. *)
659 | CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
661 type license = GPLv2plus | LGPLv2plus | GPLv2 | LGPLv2
663 let generate_header ?(extra_inputs = []) comment license =
664 let inputs = "generator/generator.ml" :: extra_inputs in
665 let c = match comment with
666 | CStyle -> pr "/* "; " *"
667 | CPlusPlusStyle -> pr "// "; "//"
668 | HashStyle -> pr "# "; "#"
669 | OCamlStyle -> pr "(* "; " *"
670 | HaskellStyle -> pr "{- "; " "
671 | PODCommentStyle -> pr "=begin comment\n\n "; "" in
672 pr "hivex generated file\n";
673 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
674 List.iter (pr "%s %s\n" c) inputs;
675 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
677 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
678 pr "%s Derived from code by Petter Nordahl-Hagen under a compatible license:\n" c;
679 pr "%s Copyright (c) 1997-2007 Petter Nordahl-Hagen.\n" c;
680 pr "%s Derived from code by Markus Stephany under a compatible license:\n" c;
681 pr "%s Copyright (c)2000-2004, Markus Stephany.\n" c;
685 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
686 pr "%s it under the terms of the GNU General Public License as published by\n" c;
687 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
688 pr "%s (at your option) any later version.\n" c;
690 pr "%s This program is distributed in the hope that it will be useful,\n" c;
691 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
692 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
693 pr "%s GNU General Public License for more details.\n" c;
695 pr "%s You should have received a copy of the GNU General Public License along\n" c;
696 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
697 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
700 pr "%s This library is free software; you can redistribute it and/or\n" c;
701 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
702 pr "%s License as published by the Free Software Foundation; either\n" c;
703 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
705 pr "%s This library is distributed in the hope that it will be useful,\n" c;
706 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
707 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
708 pr "%s Lesser General Public License for more details.\n" c;
710 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
711 pr "%s License along with this library; if not, write to the Free Software\n" c;
712 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
715 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
716 pr "%s it under the terms of the GNU General Public License as published by\n" c;
717 pr "%s the Free Software Foundation; version 2 of the License only.\n" c;
719 pr "%s This program is distributed in the hope that it will be useful,\n" c;
720 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
721 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
722 pr "%s GNU General Public License for more details.\n" c;
724 pr "%s You should have received a copy of the GNU General Public License along\n" c;
725 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
726 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
729 pr "%s This library is free software; you can redistribute it and/or\n" c;
730 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
731 pr "%s License as published by the Free Software Foundation;\n" c;
732 pr "%s version 2.1 of the License only.\n" c;
734 pr "%s This library is distributed in the hope that it will be useful,\n" c;
735 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
736 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
737 pr "%s Lesser General Public License for more details.\n" c;
739 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
740 pr "%s License along with this library; if not, write to the Free Software\n" c;
741 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
744 | CStyle -> pr " */\n"
747 | OCamlStyle -> pr " *)\n"
748 | HaskellStyle -> pr "-}\n"
749 | PODCommentStyle -> pr "\n=end comment\n"
753 (* Start of main code generation functions below this line. *)
755 let rec generate_c_header () =
756 generate_header CStyle LGPLv2;
769 /* NOTE: This API is documented in the man page hivex(3). */
772 typedef struct hive_h hive_h;
774 /* Nodes and values. */
775 typedef size_t hive_node_h;
776 typedef size_t hive_value_h;
780 # define HIVEX_NO_KEY ENOKEY
782 # define HIVEX_NO_KEY ENOENT
785 /* Pre-defined types. */
789 fun (t, old_style, new_style, description) ->
790 pr " /* %s */\n" description;
791 pr " hive_t_REG_%s,\n" new_style;
792 pr "#define hive_t_%s hive_t_REG_%s\n" old_style new_style;
798 typedef enum hive_type hive_type;
800 /* Bitmask of flags passed to hivex_open. */
803 fun (v, flag, description) ->
804 pr " /* %s */\n" description;
805 pr "#define HIVEX_OPEN_%-10s %d\n" flag v;
810 /* Array of (key, value) pairs passed to hivex_node_set_values. */
811 struct hive_set_value {
817 typedef struct hive_set_value hive_set_value;
821 pr "/* Functions. */\n";
823 (* Function declarations. *)
825 fun (shortname, style, _, _) ->
826 let name = "hivex_" ^ shortname in
827 generate_c_prototype ~extern:true name style
830 (* The visitor pattern. *)
832 /* Visit all nodes. This is specific to the C API and is not made
833 * available to other languages. This is because of the complexity
834 * of binding callbacks in other languages, but also because other
835 * languages make it much simpler to iterate over a tree.
837 struct hivex_visitor {
838 int (*node_start) (hive_h *, void *opaque, hive_node_h, const char *name);
839 int (*node_end) (hive_h *, void *opaque, hive_node_h, const char *name);
840 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);
841 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);
842 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);
843 int (*value_dword) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, int32_t);
844 int (*value_qword) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, int64_t);
845 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);
846 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);
847 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);
848 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);
851 #define HIVEX_VISIT_SKIP_BAD 1
853 extern int hivex_visit (hive_h *h, const struct hivex_visitor *visitor, size_t len, void *opaque, int flags);
854 extern int hivex_visit_node (hive_h *h, hive_node_h node, const struct hivex_visitor *visitor, size_t len, void *opaque, int flags);
858 (* Finish the header file. *)
864 #endif /* HIVEX_H_ */
867 and generate_c_prototype ?(extern = false) name style =
868 if extern then pr "extern ";
869 (match fst style with
871 | RErrDispose -> pr "int "
872 | RHive -> pr "hive_h *"
873 | RSize -> pr "size_t "
874 | RNode -> pr "hive_node_h "
875 | RNodeNotFound -> pr "hive_node_h "
876 | RNodeList -> pr "hive_node_h *"
877 | RValue -> pr "hive_value_h "
878 | RValueList -> pr "hive_value_h *"
879 | RString -> pr "char *"
880 | RStringList -> pr "char **"
881 | RLenType -> pr "int "
882 | RLenTypeVal -> pr "char *"
883 | RInt32 -> pr "int32_t "
884 | RInt64 -> pr "int64_t "
887 let comma = ref false in
890 if !comma then pr ", "; comma := true;
892 | AHive -> pr "hive_h *h"
893 | ANode n -> pr "hive_node_h %s" n
894 | AValue n -> pr "hive_value_h %s" n
895 | AString n | AStringNullable n -> pr "const char *%s" n
896 | AOpenFlags | AUnusedFlags -> pr "int flags"
897 | ASetValues -> pr "size_t nr_values, const hive_set_value *values"
898 | ASetValue -> pr "const hive_set_value *val"
900 (match fst style with
901 | RLenType | RLenTypeVal -> pr ", hive_type *t, size_t *len"
906 and generate_c_pod () =
907 generate_header PODCommentStyle GPLv2;
914 hivex - Windows Registry \"hive\" extraction library
922 fun (shortname, style, _, _) ->
923 let name = "hivex_" ^ shortname in
925 generate_c_prototype ~extern:false name style;
930 Link with I<-lhivex>.
934 Hivex is a library for extracting the contents of Windows Registry
935 \"hive\" files. It is designed to be secure against buggy or malicious
938 Unlike other tools in this area, it doesn't use the textual .REG
939 format, because parsing that is as much trouble as parsing the
940 original binary format. Instead it makes the file available
941 through a C API, and then wraps this API in higher level scripting
944 There is a separate program to export the hive as XML
945 (see L<hivexml(1)>), or to navigate the file (see L<hivexsh(1)>).
946 There is also a Perl script to export and merge the
947 file as a textual .REG (regedit) file, see L<hivexregedit(1)>.
949 If you just want to export or modify the Registry of a Windows
950 virtual machine, you should look at L<virt-win-reg(1)>.
952 Hivex is also comes with language bindings for
953 OCaml, Perl, Python and Ruby.
959 This handle describes an open hive file.
961 =head2 C<hive_node_h>
963 This is a node handle, an integer but opaque outside the library.
964 Valid node handles cannot be 0. The library returns 0 in some
965 situations to indicate an error.
969 The enum below describes the possible types for the value(s)
970 stored at each node. Note that you should not trust the
971 type field in a Windows Registry, as it very often has no
972 relationship to reality. Some applications use their own
973 types. The encoding of strings is not specified. Some
974 programs store everything (including strings) in binary blobs.
979 fun (t, _, new_style, description) ->
980 pr " /* %s */\n" description;
981 pr " hive_t_REG_%s = %d,\n" new_style t
986 =head2 C<hive_value_h>
988 This is a value handle, an integer but opaque outside the library.
989 Valid value handles cannot be 0. The library returns 0 in some
990 situations to indicate an error.
992 =head2 C<hive_set_value>
994 The typedef C<hive_set_value> is used in conjunction with the
995 C<hivex_node_set_values> call described below.
997 struct hive_set_value {
998 char *key; /* key - a UTF-8 encoded ASCIIZ string */
999 hive_type t; /* type of value field */
1000 size_t len; /* length of value field in bytes */
1001 char *value; /* value field */
1003 typedef struct hive_set_value hive_set_value;
1005 To set the default value for a node, you have to pass C<key = \"\">.
1007 Note that the C<value> field is just treated as a list of bytes, and
1008 is stored directly in the hive. The caller has to ensure correct
1009 encoding and endianness, for example converting dwords to little
1012 The correct type and encoding for values depends on the node and key
1013 in the registry, the version of Windows, and sometimes even changes
1014 between versions of Windows for the same key. We don't document it
1015 here. Often it's not documented at all.
1021 fun (shortname, style, _, longdesc) ->
1022 let name = "hivex_" ^ shortname in
1023 pr "=head2 %s\n" name;
1025 generate_c_prototype ~extern:false name style;
1030 if List.mem AUnusedFlags (snd style) then
1031 pr "The flags parameter is unused. Always pass 0.\n\n";
1033 if List.mem ASetValues (snd style) then
1034 pr "C<values> is an array of (key, value) pairs. There
1035 should be C<nr_values> elements in this array.
1037 Any existing values stored at the node are discarded, and their
1038 C<hive_value_h> handles become invalid. Thus you can remove all
1039 values stored at C<node> by passing C<nr_values = 0>.\n\n";
1041 if List.mem ASetValue (snd style) then
1042 pr "C<value> is a single (key, value) pair.
1044 Existing C<hive_value_h> handles become invalid.\n\n";
1046 (match fst style with
1049 Returns 0 on success.
1050 On error this returns -1 and sets errno.\n\n"
1053 Returns 0 on success.
1054 On error this returns -1 and sets errno.
1056 This function frees the hive handle (even if it returns an error).
1057 The hive handle must not be used again after calling this function.\n\n"
1060 Returns a new hive handle.
1061 On error this returns NULL and sets errno.\n\n"
1065 On error this returns 0 and sets errno.\n\n"
1068 Returns a node handle.
1069 On error this returns 0 and sets errno.\n\n"
1072 Returns a node handle.
1073 If the node was not found, this returns 0 without setting errno.
1074 On error this returns 0 and sets errno.\n\n"
1077 Returns a 0-terminated array of nodes.
1078 The array must be freed by the caller when it is no longer needed.
1079 On error this returns NULL and sets errno.\n\n"
1082 Returns a value handle.
1083 On error this returns 0 and sets errno.\n\n"
1086 Returns a 0-terminated array of values.
1087 The array must be freed by the caller when it is no longer needed.
1088 On error this returns NULL and sets errno.\n\n"
1092 The string must be freed by the caller when it is no longer needed.
1093 On error this returns NULL and sets errno.\n\n"
1096 Returns a NULL-terminated array of C strings.
1097 The strings and the array must all be freed by the caller when
1098 they are no longer needed.
1099 On error this returns NULL and sets errno.\n\n"
1102 Returns 0 on success.
1103 On error this returns -1 and sets errno.\n\n"
1106 The value is returned as an array of bytes (of length C<len>).
1107 The value must be freed by the caller when it is no longer needed.
1108 On error this returns NULL and sets errno.\n\n"
1109 | RInt32 | RInt64 -> ()
1114 =head1 WRITING TO HIVE FILES
1116 The hivex library supports making limited modifications to hive files.
1117 We have tried to implement this very conservatively in order to reduce
1118 the chance of corrupting your registry. However you should be careful
1119 and take back-ups, since Microsoft has never documented the hive
1120 format, and so it is possible there are nuances in the
1121 reverse-engineered format that we do not understand.
1123 To be able to modify a hive, you must pass the C<HIVEX_OPEN_WRITE>
1124 flag to C<hivex_open>, otherwise any write operation will return with
1127 The write operations shown below do not modify the on-disk file
1128 immediately. You must call C<hivex_commit> in order to write the
1129 changes to disk. If you call C<hivex_close> without committing then
1130 any writes are discarded.
1132 Hive files internally consist of a \"memory dump\" of binary blocks
1133 (like the C heap), and some of these blocks can be unused. The hivex
1134 library never reuses these unused blocks. Instead, to ensure
1135 robustness in the face of the partially understood on-disk format,
1136 hivex only allocates new blocks after the end of the file, and makes
1137 minimal modifications to existing structures in the file to point to
1138 these new blocks. This makes hivex slightly less disk-efficient than
1139 it could be, but disk is cheap, and registry modifications tend to be
1142 When deleting nodes, it is possible that this library may leave
1143 unreachable live blocks in the hive. This is because certain parts of
1144 the hive disk format such as security (sk) records and big data (db)
1145 records and classname fields are not well understood (and not
1146 documented at all) and we play it safe by not attempting to modify
1147 them. Apart from wasting a little bit of disk space, it is not
1148 thought that unreachable blocks are a problem.
1150 =head2 WRITE OPERATIONS WHICH ARE NOT SUPPORTED
1156 Changing the root node.
1160 Creating a new hive file from scratch. This is impossible at present
1161 because not all fields in the header are understood. In the hivex
1162 source tree is a file called C<images/minimal> which could be used as
1163 the basis for a new hive (but I<caveat emptor>).
1167 Modifying or deleting single values at a node.
1171 Modifying security key (sk) records or classnames.
1172 Previously we did not understand these records. However now they
1173 are well-understood and we could add support if it was required
1174 (but nothing much really uses them).
1178 =head1 VISITING ALL NODES
1180 The visitor pattern is useful if you want to visit all nodes
1181 in the tree or all nodes below a certain point in the tree.
1183 First you set up your own C<struct hivex_visitor> with your
1186 Each of these callback functions should return 0 on success or -1
1187 on error. If any callback returns -1, then the entire visit
1188 terminates immediately. If you don't need a callback function at
1189 all, set the function pointer to NULL.
1191 struct hivex_visitor {
1192 int (*node_start) (hive_h *, void *opaque, hive_node_h, const char *name);
1193 int (*node_end) (hive_h *, void *opaque, hive_node_h, const char *name);
1194 int (*value_string) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1195 hive_type t, size_t len, const char *key, const char *str);
1196 int (*value_multiple_strings) (hive_h *, void *opaque, hive_node_h,
1197 hive_value_h, hive_type t, size_t len, const char *key, char **argv);
1198 int (*value_string_invalid_utf16) (hive_h *, void *opaque, hive_node_h,
1199 hive_value_h, hive_type t, size_t len, const char *key,
1201 int (*value_dword) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1202 hive_type t, size_t len, const char *key, int32_t);
1203 int (*value_qword) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1204 hive_type t, size_t len, const char *key, int64_t);
1205 int (*value_binary) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1206 hive_type t, size_t len, const char *key, const char *value);
1207 int (*value_none) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1208 hive_type t, size_t len, const char *key, const char *value);
1209 int (*value_other) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1210 hive_type t, size_t len, const char *key, const char *value);
1211 /* If value_any callback is not NULL, then the other value_*
1212 * callbacks are not used, and value_any is called on all values.
1214 int (*value_any) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1215 hive_type t, size_t len, const char *key, const char *value);
1222 int hivex_visit (hive_h *h, const struct hivex_visitor *visitor, size_t len, void *opaque, int flags);
1224 Visit all the nodes recursively in the hive C<h>.
1226 C<visitor> should be a C<hivex_visitor> structure with callback
1227 fields filled in as required (unwanted callbacks can be set to
1228 NULL). C<len> must be the length of the 'visitor' struct (you
1229 should pass C<sizeof (struct hivex_visitor)> for this).
1231 This returns 0 if the whole recursive visit was completed
1232 successfully. On error this returns -1. If one of the callback
1233 functions returned an error than we don't touch errno. If the
1234 error was generated internally then we set errno.
1236 You can skip bad registry entries by setting C<flag> to
1237 C<HIVEX_VISIT_SKIP_BAD>. If this flag is not set, then a bad registry
1238 causes the function to return an error immediately.
1240 This function is robust if the registry contains cycles or
1241 pointers which are invalid or outside the registry. It detects
1242 these cases and returns an error.
1244 =item hivex_visit_node
1246 int hivex_visit_node (hive_h *h, hive_node_h node, const struct hivex_visitor *visitor, size_t len, void *opaque);
1248 Same as C<hivex_visit> but instead of starting out at the root, this
1253 =head1 THE STRUCTURE OF THE WINDOWS REGISTRY
1255 Note: To understand the relationship between hives and the common
1256 Windows Registry keys (like C<HKEY_LOCAL_MACHINE>) please see the
1257 Wikipedia page on the Windows Registry.
1259 The Windows Registry is split across various binary files, each
1260 file being known as a \"hive\". This library only handles a single
1261 hive file at a time.
1263 Hives are n-ary trees with a single root. Each node in the tree
1266 Each node in the tree (including non-leaf nodes) may have an
1267 arbitrary list of (key, value) pairs attached to it. It may
1268 be the case that one of these pairs has an empty key. This
1269 is referred to as the default key for the node.
1271 The (key, value) pairs are the place where the useful data is
1272 stored in the registry. The key is always a string (possibly the
1273 empty string for the default key). The value is a typed object
1274 (eg. string, int32, binary, etc.).
1276 =head2 RELATIONSHIP TO .REG FILES
1278 The hivex C library does not care about or deal with Windows .REG
1279 files. Instead we push this complexity up to the Perl
1280 L<Win::Hivex(3)> library and the Perl programs
1281 L<hivexregedit(1)> and L<virt-win-reg(1)>.
1282 Nevertheless it is useful to look at the relationship between the
1283 Registry and .REG files because they are so common.
1285 A .REG file is a textual representation of the registry, or part of the
1286 registry. The actual registry hives that Windows uses are binary
1287 files. There are a number of Windows and Linux tools that let you
1288 generate .REG files, or merge .REG files back into the registry hives.
1289 Notable amongst them is Microsoft's REGEDIT program (formerly known as
1292 A typical .REG file will contain many sections looking like this:
1294 [HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\Stack]
1295 \"@\"=\"Generic Stack\"
1296 \"TileInfo\"=\"prop:System.FileCount\"
1297 \"TilePath\"=str(2):\"%%systemroot%%\\\\system32\"
1298 \"ThumbnailCutoff\"=dword:00000000
1299 \"FriendlyTypeName\"=hex(2):40,00,25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,\\
1300 6f,00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,\\
1301 33,00,32,00,5c,00,73,00,65,00,61,00,72,00,63,00,68,00,66,00,\\
1302 6f,00,6c,00,64,00,65,00,72,00,2e,00,64,00,6c,00,6c,00,2c,00,\\
1303 2d,00,39,00,30,00,32,00,38,00,00,00,d8
1305 Taking this one piece at a time:
1307 [HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\Stack]
1309 This is the path to this node in the registry tree. The first part,
1310 C<HKEY_LOCAL_MACHINE\\SOFTWARE> means that this comes from a hive
1311 file called C<C:\\WINDOWS\\SYSTEM32\\CONFIG\\SOFTWARE>.
1312 C<\\Classes\\Stack> is the real path part,
1313 starting at the root node of the C<SOFTWARE> hive.
1315 Below the node name is a list of zero or more key-value pairs. Any
1316 interior or leaf node in the registry may have key-value pairs
1319 \"@\"=\"Generic Stack\"
1321 This is the \"default key\". In reality (ie. inside the binary hive)
1322 the key string is the empty string. In .REG files this is written as
1323 C<@> but this has no meaning either in the hives themselves or in this
1324 library. The value is a string (type 1 - see C<enum hive_type>
1327 \"TileInfo\"=\"prop:System.FileCount\"
1329 This is a regular (key, value) pair, with the value being a type 1
1330 string. Note that inside the binary file the string is likely to be
1331 UTF-16LE encoded. This library converts to and from UTF-8 strings
1332 transparently in some cases.
1334 \"TilePath\"=str(2):\"%%systemroot%%\\\\system32\"
1336 The value in this case has type 2 (expanded string) meaning that some
1337 %%...%% variables get expanded by Windows. (This library doesn't know
1338 or care about variable expansion).
1340 \"ThumbnailCutoff\"=dword:00000000
1342 The value in this case is a dword (type 4).
1344 \"FriendlyTypeName\"=hex(2):40,00,....
1346 This value is an expanded string (type 2) represented in the .REG file
1347 as a series of hex bytes. In this case the string appears to be a
1350 =head1 NOTE ON THE USE OF ERRNO
1352 Many functions in this library set errno to indicate errors. These
1353 are the values of errno you may encounter (this list is not
1360 Corrupt or unsupported Registry file format.
1368 Passed an invalid argument to the function.
1372 Followed a Registry pointer which goes outside
1373 the registry or outside a registry block.
1377 Registry contains cycles.
1381 Field in the registry out of range.
1385 Registry key already exists.
1389 Tried to write to a registry which is not opened for writing.
1393 =head1 ENVIRONMENT VARIABLES
1399 Setting HIVEX_DEBUG=1 will enable very verbose messages. This is
1400 useful for debugging problems with the library itself.
1413 L<http://libguestfs.org/>,
1416 L<http://en.wikipedia.org/wiki/Windows_Registry>.
1420 Richard W.M. Jones (C<rjones at redhat dot com>)
1424 Copyright (C) 2009-2010 Red Hat Inc.
1426 Derived from code by Petter Nordahl-Hagen under a compatible license:
1427 Copyright (C) 1997-2007 Petter Nordahl-Hagen.
1429 Derived from code by Markus Stephany under a compatible license:
1430 Copyright (C) 2000-2004 Markus Stephany.
1432 This library is free software; you can redistribute it and/or
1433 modify it under the terms of the GNU Lesser General Public
1434 License as published by the Free Software Foundation;
1435 version 2.1 of the License only.
1437 This library is distributed in the hope that it will be useful,
1438 but WITHOUT ANY WARRANTY; without even the implied warranty of
1439 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1440 Lesser General Public License for more details.
1443 (* Generate the linker script which controls the visibility of
1444 * symbols in the public ABI and ensures no other symbols get
1445 * exported accidentally.
1447 and generate_linker_script () =
1448 generate_header HashStyle GPLv2plus;
1456 List.map (fun (name, _, _, _) -> "hivex_" ^ name)
1458 let globals = List.sort compare (globals @ functions) in
1462 List.iter (pr " %s;\n") globals;
1469 and generate_ocaml_interface () =
1470 generate_header OCamlStyle LGPLv2plus;
1474 (** A [hive_h] hive file handle. *)
1478 (** Nodes and values. *)
1480 exception Error of string * Unix.error * string
1481 (** Error raised by a function.
1483 The first parameter is the name of the function which raised the error.
1484 The second parameter is the errno (see the [Unix] module). The third
1485 parameter is a human-readable string corresponding to the errno.
1487 See hivex(3) for a partial list of interesting errno values that
1488 can be generated by the library. *)
1489 exception Handle_closed of string
1490 (** This exception is raised if you call a function on a closed handle. *)
1496 fun (t, _, new_style, description) ->
1498 pr " | REG_%s (** %s *)\n" new_style description
1502 | REG_UNKNOWN of int32 (** unknown type *)
1503 (** Hive type field. *)
1509 fun (v, flag, description) ->
1510 assert (1 lsl i = v);
1511 pr " | OPEN_%s (** %s *)\n" flag description
1515 (** Open flags for {!open_file} call. *)
1522 (** (key, value) pair passed (as an array) to {!node_set_values}. *)
1526 fun (name, style, shortdesc, _) ->
1528 generate_ocaml_prototype name style;
1529 pr "(** %s *)\n" shortdesc
1532 and generate_ocaml_implementation () =
1533 generate_header OCamlStyle LGPLv2plus;
1540 exception Error of string * Unix.error * string
1541 exception Handle_closed of string
1543 (* Give the exceptions names, so they can be raised from the C code. *)
1545 Callback.register_exception \"ocaml_hivex_error\"
1546 (Error (\"\", Unix.EUNKNOWNERR 0, \"\"));
1547 Callback.register_exception \"ocaml_hivex_closed\" (Handle_closed \"\")
1553 fun (t, _, new_style, _) ->
1555 pr " | REG_%s\n" new_style
1559 | REG_UNKNOWN of int32
1565 fun (v, flag, description) ->
1566 assert (1 lsl i = v);
1567 pr " | OPEN_%s (** %s *)\n" flag description
1581 fun (name, style, _, _) ->
1582 generate_ocaml_prototype ~is_external:true name style
1585 and generate_ocaml_prototype ?(is_external = false) name style =
1586 let ocaml_name = if name = "open" then "open_file" else name in
1588 if is_external then pr "external " else pr "val ";
1589 pr "%s : " ocaml_name;
1592 | AHive -> pr "t -> "
1593 | ANode _ -> pr "node -> "
1594 | AValue _ -> pr "value -> "
1595 | AString _ -> pr "string -> "
1596 | AStringNullable _ -> pr "string option -> "
1597 | AOpenFlags -> pr "open_flag list -> "
1598 | AUnusedFlags -> ()
1599 | ASetValues -> pr "set_value array -> "
1600 | ASetValue -> pr "set_value -> "
1602 (match fst style with
1603 | RErr -> pr "unit" (* all errors are turned into exceptions *)
1604 | RErrDispose -> pr "unit"
1606 | RSize -> pr "int64"
1607 | RNode -> pr "node"
1608 | RNodeNotFound -> pr "node"
1609 | RNodeList -> pr "node array"
1610 | RValue -> pr "value"
1611 | RValueList -> pr "value array"
1612 | RString -> pr "string"
1613 | RStringList -> pr "string array"
1614 | RLenType -> pr "hive_type * int"
1615 | RLenTypeVal -> pr "hive_type * string"
1616 | RInt32 -> pr "int32"
1617 | RInt64 -> pr "int64"
1620 pr " = \"ocaml_hivex_%s\"" name;
1623 and generate_ocaml_c () =
1624 generate_header CStyle LGPLv2plus;
1635 #include <caml/config.h>
1636 #include <caml/alloc.h>
1637 #include <caml/callback.h>
1638 #include <caml/custom.h>
1639 #include <caml/fail.h>
1640 #include <caml/memory.h>
1641 #include <caml/mlvalues.h>
1642 #include <caml/signals.h>
1644 #ifdef HAVE_CAML_UNIXSUPPORT_H
1645 #include <caml/unixsupport.h>
1647 extern value unix_error_of_code (int errcode);
1650 #ifndef HAVE_CAML_RAISE_WITH_ARGS
1652 caml_raise_with_args (value tag, int nargs, value args[])
1655 CAMLxparamN (args, nargs);
1659 bucket = caml_alloc_small (1 + nargs, 0);
1660 Field(bucket, 0) = tag;
1661 for (i = 0; i < nargs; i++) Field(bucket, 1 + i) = args[i];
1669 #define Hiveh_val(v) (*((hive_h **)Data_custom_val(v)))
1670 static value Val_hiveh (hive_h *);
1671 static int HiveOpenFlags_val (value);
1672 static hive_set_value *HiveSetValue_val (value);
1673 static hive_set_value *HiveSetValues_val (value);
1674 static hive_type HiveType_val (value);
1675 static value Val_hive_type (hive_type);
1676 static value copy_int_array (size_t *);
1677 static value copy_type_len (size_t, hive_type);
1678 static value copy_type_value (const char *, size_t, hive_type);
1679 static void raise_error (const char *) Noreturn;
1680 static void raise_closed (const char *) Noreturn;
1686 fun (name, style, _, _) ->
1687 pr "/* Automatically generated wrapper for function\n";
1688 pr " * "; generate_ocaml_prototype name style;
1694 | ASetValues -> ["nrvalues"; "values"]
1695 | AUnusedFlags -> ["0"]
1696 | arg -> [name_of_argt arg]) (snd style) in
1698 match fst style with
1699 | RLenType | RLenTypeVal -> c_params @ [["&t"; "&len"]]
1701 let c_params = List.concat c_params in
1704 filter_map (function
1705 | AUnusedFlags -> None
1706 | arg -> Some (name_of_argt arg ^ "v")) (snd style) in
1708 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
1709 pr "CAMLprim value ocaml_hivex_%s (value %s" name (List.hd params);
1710 List.iter (pr ", value %s") (List.tl params); pr ");\n";
1713 pr "CAMLprim value\n";
1714 pr "ocaml_hivex_%s (value %s" name (List.hd params);
1715 List.iter (pr ", value %s") (List.tl params);
1719 pr " CAMLparam%d (%s);\n"
1720 (List.length params) (String.concat ", " params);
1721 pr " CAMLlocal1 (rv);\n";
1727 pr " hive_h *h = Hiveh_val (hv);\n";
1728 pr " if (h == NULL)\n";
1729 pr " raise_closed (\"%s\");\n" name
1731 pr " hive_node_h %s = Int_val (%sv);\n" n n
1733 pr " hive_value_h %s = Int_val (%sv);\n" n n
1735 pr " const char *%s = String_val (%sv);\n" n n
1736 | AStringNullable n ->
1737 pr " const char *%s =\n" n;
1738 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
1741 pr " int flags = HiveOpenFlags_val (flagsv);\n"
1742 | AUnusedFlags -> ()
1744 pr " int nrvalues = Wosize_val (valuesv);\n";
1745 pr " hive_set_value *values = HiveSetValues_val (valuesv);\n"
1747 pr " hive_set_value *val = HiveSetValue_val (valv);\n"
1752 match fst style with
1753 | RErr -> pr " int r;\n"; "-1"
1754 | RErrDispose -> pr " int r;\n"; "-1"
1755 | RHive -> pr " hive_h *r;\n"; "NULL"
1756 | RSize -> pr " size_t r;\n"; "0"
1757 | RNode -> pr " hive_node_h r;\n"; "0"
1760 pr " hive_node_h r;\n";
1762 | RNodeList -> pr " hive_node_h *r;\n"; "NULL"
1763 | RValue -> pr " hive_value_h r;\n"; "0"
1764 | RValueList -> pr " hive_value_h *r;\n"; "NULL"
1765 | RString -> pr " char *r;\n"; "NULL"
1766 | RStringList -> pr " char **r;\n"; "NULL"
1769 pr " size_t len;\n";
1770 pr " hive_type t;\n";
1774 pr " size_t len;\n";
1775 pr " hive_type t;\n";
1784 "-1 && errno != 0" in
1786 (* The libguestfs OCaml bindings call enter_blocking_section
1787 * here. However I don't think that is safe, because we are
1788 * holding pointers to caml strings during the call, and these
1789 * could be moved or freed by other threads. In any case, there
1790 * is very little reason to enter_blocking_section for any hivex
1791 * call, so don't do it. XXX
1793 (*pr " caml_enter_blocking_section ();\n";*)
1794 pr " r = hivex_%s (%s" name (List.hd c_params);
1795 List.iter (pr ", %s") (List.tl c_params);
1797 (*pr " caml_leave_blocking_section ();\n";*)
1800 (* Dispose of the hive handle (even if hivex_close returns error). *)
1801 (match fst style with
1803 pr " /* So we don't double-free in the finalizer. */\n";
1804 pr " Hiveh_val (hv) = NULL;\n";
1811 | AHive | ANode _ | AValue _ | AString _ | AStringNullable _
1812 | AOpenFlags | AUnusedFlags -> ()
1814 pr " free (values);\n";
1817 pr " free (val);\n";
1821 (* Check for errors. *)
1822 pr " if (r == %s)\n" error_code;
1823 pr " raise_error (\"%s\");\n" name;
1826 (match fst style with
1827 | RErr -> pr " rv = Val_unit;\n"
1828 | RErrDispose -> pr " rv = Val_unit;\n"
1829 | RHive -> pr " rv = Val_hiveh (r);\n"
1830 | RSize -> pr " rv = caml_copy_int64 (r);\n"
1831 | RNode -> pr " rv = Val_int (r);\n"
1833 pr " if (r == 0)\n";
1834 pr " caml_raise_not_found ();\n";
1836 pr " rv = Val_int (r);\n"
1838 pr " rv = copy_int_array (r);\n";
1840 | RValue -> pr " rv = Val_int (r);\n"
1842 pr " rv = copy_int_array (r);\n";
1845 pr " rv = caml_copy_string (r);\n";
1848 pr " rv = caml_copy_string_array ((const char **) r);\n";
1849 pr " for (int i = 0; r[i] != NULL; ++i) free (r[i]);\n";
1851 | RLenType -> pr " rv = copy_type_len (len, t);\n"
1853 pr " rv = copy_type_value (r, len, t);\n";
1855 | RInt32 -> pr " rv = caml_copy_int32 (r);\n"
1856 | RInt64 -> pr " rv = caml_copy_int64 (r);\n"
1859 pr " CAMLreturn (rv);\n";
1867 HiveOpenFlags_val (value v)
1872 while (v != Val_int (0)) {
1874 flags |= 1 << Int_val (v2);
1881 static hive_set_value *
1882 HiveSetValue_val (value v)
1884 hive_set_value *val = malloc (sizeof (hive_set_value));
1886 val->key = String_val (Field (v, 0));
1887 val->t = HiveType_val (Field (v, 1));
1888 val->len = caml_string_length (Field (v, 2));
1889 val->value = String_val (Field (v, 2));
1894 static hive_set_value *
1895 HiveSetValues_val (value v)
1897 size_t nr_values = Wosize_val (v);
1898 hive_set_value *values = malloc (nr_values * sizeof (hive_set_value));
1902 for (i = 0; i < nr_values; ++i) {
1904 values[i].key = String_val (Field (v2, 0));
1905 values[i].t = HiveType_val (Field (v2, 1));
1906 values[i].len = caml_string_length (Field (v2, 2));
1907 values[i].value = String_val (Field (v2, 2));
1914 HiveType_val (value v)
1917 return Int_val (v); /* REG_NONE etc. */
1919 return Int32_val (Field (v, 0)); /* REG_UNKNOWN of int32 */
1923 Val_hive_type (hive_type t)
1929 CAMLreturn (Val_int (t));
1931 rv = caml_alloc (1, 0); /* REG_UNKNOWN of int32 */
1932 v = caml_copy_int32 (t);
1933 caml_modify (&Field (rv, 0), v);
1939 copy_int_array (size_t *xs)
1945 for (nr = 0; xs[nr] != 0; ++nr)
1948 CAMLreturn (Atom (0));
1950 rv = caml_alloc (nr, 0);
1951 for (i = 0; i < nr; ++i) {
1952 v = Val_int (xs[i]);
1953 Store_field (rv, i, v); /* Safe because v is not a block. */
1960 copy_type_len (size_t len, hive_type t)
1965 rv = caml_alloc (2, 0);
1966 v = Val_hive_type (t);
1967 Store_field (rv, 0, v);
1969 Store_field (rv, 1, v);
1974 copy_type_value (const char *r, size_t len, hive_type t)
1979 rv = caml_alloc (2, 0);
1980 v = Val_hive_type (t);
1981 Store_field (rv, 0, v);
1982 v = caml_alloc_string (len);
1983 memcpy (String_val (v), r, len);
1984 caml_modify (&Field (rv, 1), v);
1988 /* Raise exceptions. */
1990 raise_error (const char *function)
1992 /* Save errno early in case it gets trashed. */
1996 CAMLlocal3 (v1, v2, v3);
1998 v1 = caml_copy_string (function);
1999 v2 = unix_error_of_code (err);
2000 v3 = caml_copy_string (strerror (err));
2001 value vvv[] = { v1, v2, v3 };
2002 caml_raise_with_args (*caml_named_value (\"ocaml_hivex_error\"), 3, vvv);
2008 raise_closed (const char *function)
2013 v = caml_copy_string (function);
2014 caml_raise_with_arg (*caml_named_value (\"ocaml_hivex_closed\"), v);
2019 /* Allocate handles and deal with finalization. */
2021 hivex_finalize (value hv)
2023 hive_h *h = Hiveh_val (hv);
2024 if (h) hivex_close (h);
2027 static struct custom_operations hivex_custom_operations = {
2028 (char *) \"hivex_custom_operations\",
2030 custom_compare_default,
2031 custom_hash_default,
2032 custom_serialize_default,
2033 custom_deserialize_default
2037 Val_hiveh (hive_h *h)
2042 rv = caml_alloc_custom (&hivex_custom_operations,
2043 sizeof (hive_h *), 0, 1);
2050 and generate_perl_pm () =
2051 generate_header HashStyle LGPLv2plus;
2058 Win::Hivex - Perl bindings for reading and writing Windows Registry hive files
2064 $h = Win::Hivex->open ('SOFTWARE');
2065 $root_node = $h->root ();
2066 print $h->node_name ($root_node);
2070 The C<Win::Hivex> module provides a Perl XS binding to the
2071 L<hivex(3)> API for reading and writing Windows Registry binary
2076 All errors turn into calls to C<croak> (see L<Carp(3)>).
2090 XSLoader::load ('Win::Hivex');
2094 $h = Win::Hivex->open ($filename,";
2098 pr "\n [%s => 1,]" (String.lowercase flag)
2103 Open a Windows Registry binary hive file.
2105 The C<verbose> and C<debug> flags enable different levels of
2108 The C<write> flag is required if you will be modifying the
2109 hive file (see L<hivex(3)/WRITING TO HIVE FILES>).
2111 This function returns a hive handle. The hive handle is
2112 closed automatically when its reference count drops to 0.
2118 my $class = ref ($proto) || $proto;
2119 my $filename = shift;
2126 fun (n, flag, description) ->
2127 pr " # %s\n" description;
2128 pr " $flags += %d if $flags{%s};\n" n (String.lowercase flag)
2133 my $self = Win::Hivex::_open ($filename, $flags);
2134 bless $self, $class;
2141 fun (name, style, _, longdesc) ->
2142 (* The close call isn't explicit in Perl: handles are closed
2143 * when their reference count drops to 0.
2145 * The open call is coded specially in Perl.
2147 * Therefore we don't generate prototypes for these two calls:
2149 if fst style <> RErrDispose && List.hd (snd style) = AHive then (
2150 let longdesc = replace_str longdesc "C<hivex_" "C<" in
2151 pr "=item %s\n\n " name;
2152 generate_perl_prototype name style;
2154 pr "%s\n\n" longdesc;
2156 (match fst style with
2168 This returns a size.\n\n"
2171 This returns a node handle.\n\n"
2174 This returns a node handle, or C<undef> if the node was not found.\n\n"
2177 This returns a list of node handles.\n\n"
2180 This returns a value handle.\n\n"
2183 This returns a list of value handles.\n\n"
2186 if List.mem ASetValues (snd style) then
2187 pr "C<@values> is an array of (keys, value) pairs.
2188 Each element should be a hashref containing C<key>, C<t> (type)
2191 Any existing values stored at the node are discarded, and their
2192 C<value> handles become invalid. Thus you can remove all
2193 values stored at C<node> by passing C<@values = []>.\n\n"
2206 Copyright (C) %s Red Hat Inc.
2210 Please see the file COPYING.LIB for the full license.
2216 L<http://libguestfs.org>,
2222 and generate_perl_prototype name style =
2224 (match fst style with
2227 | RHive -> pr "$h = "
2228 | RSize -> pr "$size = "
2230 | RNodeNotFound -> pr "$node = "
2231 | RNodeList -> pr "@nodes = "
2232 | RValue -> pr "$value = "
2233 | RValueList -> pr "@values = "
2234 | RString -> pr "$string = "
2235 | RStringList -> pr "@strings = "
2236 | RLenType -> pr "($type, $len) = "
2237 | RLenTypeVal -> pr "($type, $data) = "
2238 | RInt32 -> pr "$int32 = "
2239 | RInt64 -> pr "$int64 = "
2242 let args = List.tl (snd style) in
2244 (* AUnusedFlags is dropped in the bindings. *)
2245 let args = List.filter ((<>) AUnusedFlags) args in
2249 let comma = ref false in
2252 if !comma then pr ", "; comma := true;
2257 | AString n -> pr "$%s" n
2258 | AStringNullable n -> pr "[$%s|undef]" n
2259 | AOpenFlags -> pr "[flags]"
2260 | AUnusedFlags -> assert false
2261 | ASetValues -> pr "\\@values"
2262 | ASetValue -> pr "$val"
2267 and generate_perl_xs () =
2268 generate_header CStyle LGPLv2plus;
2271 #include \"EXTERN.h\"
2277 #include <inttypes.h>
2280 my_newSVll(long long val) {
2281 #ifdef USE_64_BIT_ALL
2282 return newSViv(val);
2286 len = snprintf(buf, 100, \"%%\" PRId64, val);
2287 return newSVpv(buf, len);
2293 my_newSVull(unsigned long long val) {
2294 #ifdef USE_64_BIT_ALL
2295 return newSVuv(val);
2299 len = snprintf(buf, 100, \"%%\" PRIu64, val);
2300 return newSVpv(buf, len);
2306 /* http://www.perlmonks.org/?node_id=680842 */
2308 XS_unpack_charPtrPtr (SV *arg) {
2313 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
2314 croak (\"array reference expected\");
2316 av = (AV *)SvRV (arg);
2317 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
2319 croak (\"malloc failed\");
2321 for (i = 0; i <= av_len (av); i++) {
2322 SV **elem = av_fetch (av, i, 0);
2324 if (!elem || !*elem)
2325 croak (\"missing element in list\");
2327 ret[i] = SvPV_nolen (*elem);
2336 /* Handle set_values parameter. */
2337 typedef struct pl_set_values {
2339 hive_set_value *values;
2342 static pl_set_values
2343 unpack_pl_set_values (SV *sv)
2349 if (!sv || !SvOK (sv) || !SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV)
2350 croak (\"array reference expected\");
2352 av = (AV *)SvRV(sv);
2353 ret.nr_values = av_len (av) + 1;
2354 ret.values = malloc (ret.nr_values * sizeof (hive_set_value));
2356 croak (\"malloc failed\");
2358 for (i = 0; i <= av_len (av); i++) {
2359 SV **hvp = av_fetch (av, i, 0);
2361 if (!hvp || !*hvp || !SvROK (*hvp) || SvTYPE (SvRV (*hvp)) != SVt_PVHV)
2362 croak (\"missing element in list or not a hash ref\");
2364 HV *hv = (HV *)SvRV(*hvp);
2367 svp = hv_fetch (hv, \"key\", 3, 0);
2369 croak (\"missing 'key' in hash\");
2370 ret.values[i].key = SvPV_nolen (*svp);
2372 svp = hv_fetch (hv, \"t\", 1, 0);
2374 croak (\"missing 't' in hash\");
2375 ret.values[i].t = SvIV (*svp);
2377 svp = hv_fetch (hv, \"value\", 5, 0);
2379 croak (\"missing 'value' in hash\");
2380 ret.values[i].value = SvPV (*svp, ret.values[i].len);
2386 static hive_set_value *
2387 unpack_set_value (SV *sv)
2389 hive_set_value *ret;
2391 if (!sv || !SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVHV)
2392 croak (\"not a hash ref\");
2394 ret = malloc (sizeof (hive_set_value));
2396 croak (\"malloc failed\");
2398 HV *hv = (HV *)SvRV(sv);
2401 svp = hv_fetch (hv, \"key\", 3, 0);
2403 croak (\"missing 'key' in hash\");
2404 ret->key = SvPV_nolen (*svp);
2406 svp = hv_fetch (hv, \"t\", 1, 0);
2408 croak (\"missing 't' in hash\");
2409 ret->t = SvIV (*svp);
2411 svp = hv_fetch (hv, \"value\", 5, 0);
2413 croak (\"missing 'value' in hash\");
2414 ret->value = SvPV (*svp, ret->len);
2419 MODULE = Win::Hivex PACKAGE = Win::Hivex
2424 _open (filename, flags)
2428 RETVAL = hivex_open (filename, flags);
2430 croak (\"hivex_open: %%s: %%s\", filename, strerror (errno));
2438 if (hivex_close (h) == -1)
2439 croak (\"hivex_close: %%s\", strerror (errno));
2444 fun (name, style, _, longdesc) ->
2445 (* The close and open calls are handled specially above. *)
2446 if fst style <> RErrDispose && List.hd (snd style) = AHive then (
2447 (match fst style with
2448 | RErr -> pr "void\n"
2449 | RErrDispose -> failwith "perl bindings cannot handle a call which disposes of the handle"
2450 | RHive -> failwith "perl bindings cannot handle a call which returns a handle"
2455 | RString -> pr "SV *\n"
2460 | RLenTypeVal -> pr "void\n"
2461 | RInt32 -> pr "SV *\n"
2462 | RInt64 -> pr "SV *\n"
2465 (* Call and arguments. *)
2467 filter_map (function
2468 | AUnusedFlags -> None
2469 | arg -> Some (name_of_argt arg)) (snd style) in
2473 | AUnusedFlags -> "0"
2474 | ASetValues -> "values.nr_values, values.values"
2475 | arg -> name_of_argt arg) (snd style) in
2477 pr "%s (%s)\n" name (String.concat ", " perl_params);
2488 | AStringNullable n ->
2489 (* http://www.perlmonks.org/?node_id=554277 *)
2490 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n i i
2493 | AUnusedFlags -> ()
2495 pr " pl_set_values values = unpack_pl_set_values (ST(%d));\n" i
2497 pr " hive_set_value *val = unpack_set_value (ST(%d));\n" i
2504 pr " free (values.values);\n"
2507 | AHive | ANode _ | AValue _ | AString _ | AStringNullable _
2508 | AOpenFlags | AUnusedFlags -> ()
2513 (match fst style with
2518 pr " r = hivex_%s (%s);\n"
2519 name (String.concat ", " c_params);
2521 pr " if (r == -1)\n";
2522 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2525 | RErrDispose -> assert false
2526 | RHive -> assert false
2532 pr " /* hive_node_h = hive_value_h = size_t so we cheat\n";
2533 pr " here to simplify the generator */\n";
2536 pr " r = hivex_%s (%s);\n"
2537 name (String.concat ", " c_params);
2539 pr " if (r == 0)\n";
2540 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2542 pr " RETVAL = newSViv (r);\n";
2548 pr " hive_node_h r;\n";
2551 pr " r = hivex_%s (%s);\n"
2552 name (String.concat ", " c_params);
2554 pr " if (r == 0 && errno != 0)\n";
2555 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2557 pr " if (r == 0)\n";
2558 pr " RETVAL = &PL_sv_undef;\n";
2560 pr " RETVAL = newSViv (r);\n";
2568 pr " r = hivex_%s (%s);\n"
2569 name (String.concat ", " c_params);
2571 pr " if (r == NULL)\n";
2572 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2574 pr " RETVAL = newSVpv (r, 0);\n";
2585 pr " r = hivex_%s (%s);\n"
2586 name (String.concat ", " c_params);
2588 pr " if (r == NULL)\n";
2589 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2591 pr " for (n = 0; r[n] != 0; ++n) /**/;\n";
2592 pr " EXTEND (SP, n);\n";
2593 pr " for (i = 0; i < n; ++i)\n";
2594 pr " PUSHs (sv_2mortal (newSViv (r[i])));\n";
2602 pr " r = hivex_%s (%s);\n"
2603 name (String.concat ", " c_params);
2605 pr " if (r == NULL)\n";
2606 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2608 pr " for (n = 0; r[n] != NULL; ++n) /**/;\n";
2609 pr " EXTEND (SP, n);\n";
2610 pr " for (i = 0; i < n; ++i) {\n";
2611 pr " PUSHs (sv_2mortal (newSVpv (r[i], 0)));\n";
2612 pr " free (r[i]);\n";
2619 pr " size_t len;\n";
2620 pr " hive_type type;\n";
2622 pr " r = hivex_%s (%s, &type, &len);\n"
2623 name (String.concat ", " c_params);
2625 pr " if (r == -1)\n";
2626 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2628 pr " EXTEND (SP, 2);\n";
2629 pr " PUSHs (sv_2mortal (newSViv (type)));\n";
2630 pr " PUSHs (sv_2mortal (newSViv (len)));\n";
2635 pr " size_t len;\n";
2636 pr " hive_type type;\n";
2638 pr " r = hivex_%s (%s, &type, &len);\n"
2639 name (String.concat ", " c_params);
2641 pr " if (r == NULL)\n";
2642 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2644 pr " EXTEND (SP, 2);\n";
2645 pr " PUSHs (sv_2mortal (newSViv (type)));\n";
2646 pr " PUSHs (sv_2mortal (newSVpvn (r, len)));\n";
2654 pr " r = hivex_%s (%s);\n"
2655 name (String.concat ", " c_params);
2657 pr " if (r == -1 && errno != 0)\n";
2658 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2660 pr " RETVAL = newSViv (r);\n";
2669 pr " r = hivex_%s (%s);\n"
2670 name (String.concat ", " c_params);
2672 pr " if (r == -1 && errno != 0)\n";
2673 pr " croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2675 pr " RETVAL = my_newSVll (r);\n";
2683 and generate_python_c () =
2684 generate_header CStyle LGPLv2plus;
2687 #define PY_SSIZE_T_CLEAN 1
2690 #if PY_VERSION_HEX < 0x02050000
2691 typedef int Py_ssize_t;
2692 #define PY_SSIZE_T_MAX INT_MAX
2693 #define PY_SSIZE_T_MIN INT_MIN
2700 #include \"hivex.h\"
2702 #ifndef HAVE_PYCAPSULE_NEW
2710 get_handle (PyObject *obj)
2713 assert (obj != Py_None);
2714 #ifndef HAVE_PYCAPSULE_NEW
2715 return ((Pyhivex_Object *) obj)->h;
2717 return (hive_h *) PyCapsule_GetPointer(obj, \"hive_h\");
2722 put_handle (hive_h *h)
2725 #ifndef HAVE_PYCAPSULE_NEW
2727 PyCObject_FromVoidPtrAndDesc ((void *) h, (char *) \"hive_h\", NULL);
2729 return PyCapsule_New ((void *) h, \"hive_h\", NULL);
2733 /* This returns pointers into the Python objects, which should
2737 get_value (PyObject *v, hive_set_value *ret)
2741 obj = PyDict_GetItemString (v, \"key\");
2743 PyErr_SetString (PyExc_RuntimeError, \"no 'key' element in dictionary\");
2746 if (!PyString_Check (obj)) {
2747 PyErr_SetString (PyExc_RuntimeError, \"'key' element is not a string\");
2750 ret->key = PyString_AsString (obj);
2752 obj = PyDict_GetItemString (v, \"t\");
2754 PyErr_SetString (PyExc_RuntimeError, \"no 't' element in dictionary\");
2757 if (!PyInt_Check (obj)) {
2758 PyErr_SetString (PyExc_RuntimeError, \"'t' element is not an integer\");
2761 ret->t = PyInt_AsLong (obj);
2763 obj = PyDict_GetItemString (v, \"value\");
2765 PyErr_SetString (PyExc_RuntimeError, \"no 'value' element in dictionary\");
2768 if (!PyString_Check (obj)) {
2769 PyErr_SetString (PyExc_RuntimeError, \"'value' element is not a string\");
2772 ret->value = PyString_AsString (obj);
2773 ret->len = PyString_Size (obj);
2778 typedef struct py_set_values {
2780 hive_set_value *values;
2784 get_values (PyObject *v, py_set_values *ret)
2789 if (!PyList_Check (v)) {
2790 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
2794 slen = PyList_Size (v);
2796 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
2799 len = (size_t) slen;
2800 ret->nr_values = len;
2801 ret->values = malloc (len * sizeof (hive_set_value));
2803 PyErr_SetString (PyExc_RuntimeError, strerror (errno));
2807 for (i = 0; i < len; ++i) {
2808 if (get_value (PyList_GetItem (v, i), &(ret->values[i])) == -1) {
2818 put_string_list (char * const * const argv)
2823 for (argc = 0; argv[argc] != NULL; ++argc)
2826 list = PyList_New (argc);
2827 for (i = 0; i < argc; ++i)
2828 PyList_SetItem (list, i, PyString_FromString (argv[i]));
2834 free_strings (char **argv)
2838 for (argc = 0; argv[argc] != NULL; ++argc)
2843 /* Since hive_node_t is the same as hive_value_t this also works for values. */
2845 put_node_list (hive_node_h *nodes)
2850 for (argc = 0; nodes[argc] != 0; ++argc)
2853 list = PyList_New (argc);
2854 for (i = 0; i < argc; ++i)
2855 PyList_SetItem (list, i, PyLong_FromLongLong ((long) nodes[i]));
2861 put_len_type (size_t len, hive_type t)
2863 PyObject *r = PyTuple_New (2);
2864 PyTuple_SetItem (r, 0, PyInt_FromLong ((long) t));
2865 PyTuple_SetItem (r, 1, PyLong_FromLongLong ((long) len));
2870 put_val_type (char *val, size_t len, hive_type t)
2872 PyObject *r = PyTuple_New (2);
2873 PyTuple_SetItem (r, 0, PyInt_FromLong ((long) t));
2874 PyTuple_SetItem (r, 1, PyString_FromStringAndSize (val, len));
2880 (* Generate functions. *)
2882 fun (name, style, _, longdesc) ->
2883 pr "static PyObject *\n";
2884 pr "py_hivex_%s (PyObject *self, PyObject *args)\n" name;
2886 pr " PyObject *py_r;\n";
2889 match fst style with
2890 | RErr -> pr " int r;\n"; "-1"
2891 | RErrDispose -> pr " int r;\n"; "-1"
2892 | RHive -> pr " hive_h *r;\n"; "NULL"
2893 | RSize -> pr " size_t r;\n"; "0"
2894 | RNode -> pr " hive_node_h r;\n"; "0"
2897 pr " hive_node_h r;\n";
2899 | RNodeList -> pr " hive_node_h *r;\n"; "NULL"
2900 | RValue -> pr " hive_value_h r;\n"; "0"
2901 | RValueList -> pr " hive_value_h *r;\n"; "NULL"
2902 | RString -> pr " char *r;\n"; "NULL"
2903 | RStringList -> pr " char **r;\n"; "NULL"
2906 pr " size_t len;\n";
2907 pr " hive_type t;\n";
2911 pr " size_t len;\n";
2912 pr " hive_type t;\n";
2921 "-1 && errno != 0" in
2923 (* Call and arguments. *)
2926 | AUnusedFlags -> "0"
2927 | ASetValues -> "values.nr_values, values.values"
2928 | ASetValue -> "&val"
2929 | arg -> name_of_argt arg) (snd style) in
2931 match fst style with
2932 | RLenType | RLenTypeVal -> c_params @ ["&t"; "&len"]
2939 pr " PyObject *py_h;\n"
2944 | AStringNullable n ->
2948 | AUnusedFlags -> ()
2950 pr " py_set_values values;\n";
2951 pr " PyObject *py_values;\n"
2953 pr " hive_set_value val;\n";
2954 pr " PyObject *py_val;\n"
2959 (* Convert the required parameters. *)
2960 pr " if (!PyArg_ParseTuple (args, (char *) \"";
2970 | AStringNullable n ->
2974 | AUnusedFlags -> ()
2980 pr ":hivex_%s\"" name;
2990 | AStringNullable n ->
2994 | AUnusedFlags -> ()
3002 pr " return NULL;\n";
3004 (* Convert some Python argument types to C. *)
3008 pr " h = get_handle (py_h);\n"
3014 | AUnusedFlags -> ()
3016 pr " if (get_values (py_values, &values) == -1)\n";
3017 pr " return NULL;\n"
3019 pr " if (get_value (py_val, &val) == -1)\n";
3020 pr " return NULL;\n"
3023 (* Call the C function. *)
3024 pr " r = hivex_%s (%s);\n" name (String.concat ", " c_params);
3026 (* Free up arguments. *)
3029 | AHive | ANode _ | AValue _
3030 | AString _ | AStringNullable _
3031 | AOpenFlags | AUnusedFlags -> ()
3033 pr " free (values.values);\n"
3037 (* Check for errors from C library. *)
3038 pr " if (r == %s) {\n" error_code;
3039 pr " PyErr_SetString (PyExc_RuntimeError,\n";
3040 pr " strerror (errno));\n";
3041 pr " return NULL;\n";
3045 (* Convert return value to Python. *)
3046 (match fst style with
3049 pr " Py_INCREF (Py_None);\n";
3050 pr " py_r = Py_None;\n"
3052 pr " py_r = put_handle (r);\n"
3055 pr " py_r = PyLong_FromLongLong (r);\n"
3058 pr " py_r = PyLong_FromLongLong (r);\n";
3060 pr " Py_INCREF (Py_None);\n";
3061 pr " py_r = Py_None;\n";
3065 pr " py_r = put_node_list (r);\n";
3068 pr " py_r = PyLong_FromLongLong (r);\n"
3070 pr " py_r = PyString_FromString (r);\n";
3073 pr " py_r = put_string_list (r);\n";
3074 pr " free_strings (r);\n"
3076 pr " py_r = put_len_type (len, t);\n"
3078 pr " py_r = put_val_type (r, len, t);\n";
3081 pr " py_r = PyInt_FromLong ((long) r);\n"
3083 pr " py_r = PyLong_FromLongLong (r);\n"
3085 pr " return py_r;\n";
3090 (* Table of functions. *)
3091 pr "static PyMethodDef methods[] = {\n";
3093 fun (name, _, _, _) ->
3094 pr " { (char *) \"%s\", py_hivex_%s, METH_VARARGS, NULL },\n"
3097 pr " { NULL, NULL, 0, NULL }\n";
3101 (* Init function. *)
3104 initlibhivexmod (void)
3106 static int initialized = 0;
3108 if (initialized) return;
3109 Py_InitModule ((char *) \"libhivexmod\", methods);
3114 and generate_python_py () =
3115 generate_header HashStyle LGPLv2plus;
3118 u\"\"\"Python bindings for hivex
3121 h = hivex.Hivex (filename)
3123 The hivex module provides Python bindings to the hivex API for
3124 examining and modifying Windows Registry 'hive' files.
3126 Read the hivex(3) man page to find out how to use the API.
3132 \"\"\"Instances of this class are hivex API handles.\"\"\"
3134 def __init__ (self, filename";
3137 fun (_, flag, _) -> pr ", %s = False" (String.lowercase flag)
3141 \"\"\"Create a new hivex handle.\"\"\"
3146 fun (n, flag, description) ->
3147 pr " # %s\n" description;
3148 pr " if %s: flags += %d\n" (String.lowercase flag) n
3151 pr " self._o = libhivexmod.open (filename, flags)
3154 libhivexmod.close (self._o)
3159 fun (name, style, shortdesc, _) ->
3160 (* The close and open calls are handled specially above. *)
3161 if fst style <> RErrDispose && List.hd (snd style) = AHive then (
3162 let args = List.tl (snd style) in
3163 let args = List.filter (
3164 function AOpenFlags | AUnusedFlags -> false
3168 pr " def %s (self" name;
3169 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
3171 pr " u\"\"\"%s\"\"\"\n" shortdesc;
3172 pr " return libhivexmod.%s (self._o" name;
3177 | AHive -> assert false
3178 | ANode n | AValue n
3179 | AString n | AStringNullable n -> pr "%s" n
3181 | AUnusedFlags -> assert false
3182 | ASetValues -> pr "values"
3183 | ASetValue -> pr "val"
3190 and generate_ruby_c () =
3191 generate_header CStyle LGPLv2plus;
3200 #include \"hivex.h\"
3202 #include \"extconf.h\"
3204 /* For Ruby < 1.9 */
3206 #define RARRAY_LEN(r) (RARRAY((r))->len)
3209 static VALUE m_hivex; /* hivex module */
3210 static VALUE c_hivex; /* hive_h handle */
3211 static VALUE e_Error; /* used for all errors */
3214 ruby_hivex_free (void *hvp)
3223 get_value (VALUE valv, hive_set_value *val)
3225 VALUE key = rb_hash_lookup (valv, ID2SYM (rb_intern (\"key\")));
3226 VALUE type = rb_hash_lookup (valv, ID2SYM (rb_intern (\"type\")));
3227 VALUE value = rb_hash_lookup (valv, ID2SYM (rb_intern (\"value\")));
3229 val->key = StringValueCStr (key);
3230 val->t = NUM2ULL (type);
3231 val->len = RSTRING (value)->len;
3232 val->value = RSTRING (value)->ptr;
3235 static hive_set_value *
3236 get_values (VALUE valuesv, size_t *nr_values)
3239 hive_set_value *ret;
3241 *nr_values = RARRAY_LEN (valuesv);
3242 ret = malloc (sizeof (*ret) * *nr_values);
3246 for (i = 0; i < *nr_values; ++i) {
3247 VALUE v = rb_ary_entry (valuesv, i);
3248 get_value (v, &ret[i]);
3257 fun (name, (ret, args), shortdesc, longdesc) ->
3259 (* Generate rdoc. *)
3260 let doc = replace_str longdesc "C<hivex_" "C<h." in
3261 let doc = pod2text ~width:60 name doc in
3262 let doc = String.concat "\n * " doc in
3263 let doc = trim doc in
3267 | AHive :: args -> "h." ^ name, args
3268 | args -> "Hivex::" ^ name, args in
3269 let args = filter_map (
3271 | AUnusedFlags -> None
3272 | args -> Some (name_of_argt args)
3274 let args = String.concat ", " args in
3278 | RErr | RErrDispose -> "nil"
3279 | RHive -> "Hivex::Hivex"
3280 | RSize | RNode | RNodeNotFound -> "integer"
3281 | RNodeList -> "list"
3282 | RValue -> "integer"
3283 | RValueList -> "list"
3284 | RString -> "string"
3285 | RStringList -> "list"
3286 | RLenType -> "hash"
3287 | RLenTypeVal -> "hash"
3288 | RInt32 -> "integer"
3289 | RInt64 -> "integer" in
3300 * (For the C API documentation for this function, see
3301 * +hivex_%s+[http://libguestfs.org/hivex.3.html#hivex_%s]).
3303 " call args ret shortdesc doc name name in
3305 (* Generate the function. *)
3306 pr "static VALUE\n";
3307 pr "ruby_hivex_%s (" name;
3310 (* If the first argument is not AHive, then this is a module-level
3311 * function, and Ruby passes an implicit module argument which we
3312 * must ignore. Otherwise the first argument is the hive handle.
3316 | AHive :: args -> pr "VALUE hv"; args
3317 | args -> pr "VALUE modulev"; args in
3320 | AUnusedFlags -> ()
3322 pr ", VALUE %sv" (name_of_argt arg)
3332 pr " Data_Get_Struct (hv, hive_h, h);\n";
3334 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\",\n";
3335 pr " \"%s\");\n" name;
3337 pr " hive_node_h %s = NUM2ULL (%sv);\n" n n
3339 pr " hive_value_h %s = NUM2ULL (%sv);\n" n n
3341 pr " const char *%s = StringValueCStr (%sv);\n" n n;
3342 | AStringNullable n ->
3343 pr " const char *%s =\n" n;
3344 pr " !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n
3346 pr " int flags = 0;\n";
3349 pr " if (RTEST (rb_hash_lookup (flagsv, ID2SYM (rb_intern (\"%s\")))))\n"
3350 (String.lowercase flag);
3351 pr " flags += %d;\n" n
3353 | AUnusedFlags -> ()
3355 pr " size_t nr_values;\n";
3356 pr " hive_set_value *values;\n";
3357 pr " values = get_values (valuesv, &nr_values);\n"
3359 pr " hive_set_value val;\n";
3360 pr " get_value (valv, &val);\n"
3366 | RErr -> pr " int r;\n"; "-1"
3367 | RErrDispose -> pr " int r;\n"; "-1"
3368 | RHive -> pr " hive_h *r;\n"; "NULL"
3369 | RSize -> pr " size_t r;\n"; "0"
3370 | RNode -> pr " hive_node_h r;\n"; "0"
3373 pr " hive_node_h r;\n";
3375 | RNodeList -> pr " hive_node_h *r;\n"; "NULL"
3376 | RValue -> pr " hive_value_h r;\n"; "0"
3377 | RValueList -> pr " hive_value_h *r;\n"; "NULL"
3378 | RString -> pr " char *r;\n"; "NULL"
3379 | RStringList -> pr " char **r;\n"; "NULL"
3382 pr " size_t len;\n";
3383 pr " hive_type t;\n";
3387 pr " size_t len;\n";
3388 pr " hive_type t;\n";
3397 "-1 && errno != 0" in
3402 | ASetValues -> ["nr_values"; "values"]
3403 | ASetValue -> ["&val"]
3404 | AUnusedFlags -> ["0"]
3405 | arg -> [name_of_argt arg]) args in
3408 | RLenType | RLenTypeVal -> c_params @ [["&t"; "&len"]]
3410 let c_params = List.concat c_params in
3412 pr " r = hivex_%s (%s" name (List.hd c_params);
3413 List.iter (pr ", %s") (List.tl c_params);
3417 (* Dispose of the hive handle (even if hivex_close returns error). *)
3420 pr " /* So we don't double-free in the finalizer. */\n";
3421 pr " DATA_PTR (hv) = NULL;\n";
3434 | AUnusedFlags -> ()
3436 pr " free (values);\n"
3440 (* Check for errors from C library. *)
3441 pr " if (r == %s)\n" error_code;
3442 pr " rb_raise (e_Error, \"%%s\", strerror (errno));\n";
3446 | RErr | RErrDispose ->
3447 pr " return Qnil;\n"
3449 pr " return Data_Wrap_Struct (c_hivex, NULL, ruby_hivex_free, r);\n"
3454 pr " return ULL2NUM (r);\n"
3456 pr " return INT2NUM (r);\n"
3459 pr " return ULL2NUM (r);\n";
3461 pr " return Qnil;\n"
3464 pr " size_t i, len = 0;\n";
3465 pr " for (i = 0; r[i] != 0; ++i) len++;\n";
3466 pr " VALUE rv = rb_ary_new2 (len);\n";
3467 pr " for (i = 0; r[i] != 0; ++i)\n";
3468 pr " rb_ary_push (rv, ULL2NUM (r[i]));\n";
3472 pr " VALUE rv = rb_str_new2 (r);\n";
3476 pr " size_t i, len = 0;\n";
3477 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
3478 pr " VALUE rv = rb_ary_new2 (len);\n";
3479 pr " for (i = 0; r[i] != NULL; ++i) {\n";
3480 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
3481 pr " free (r[i]);\n";
3486 pr " VALUE rv = rb_hash_new ();\n";
3487 pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"len\")), INT2NUM (len));\n";
3488 pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"type\")), INT2NUM (t));\n";
3491 pr " VALUE rv = rb_hash_new ();\n";
3492 pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"len\")), INT2NUM (len));\n";
3493 pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"type\")), INT2NUM (t));\n";
3494 pr " rb_hash_aset (rv, ID2SYM (rb_intern (\"value\")), rb_str_new (r, len));\n";
3504 /* Initialize the module. */
3507 m_hivex = rb_define_module (\"Hivex\");
3508 c_hivex = rb_define_class_under (m_hivex, \"Hivex\", rb_cObject);
3509 e_Error = rb_define_class_under (m_hivex, \"Error\", rb_eStandardError);
3511 /* XXX How to pass arguments? */
3513 #ifdef HAVE_RB_DEFINE_ALLOC_FUNC
3514 rb_define_alloc_func (c_hivex, ruby_hivex_open);
3522 fun (name, (_, args), _, _) ->
3523 let args = List.filter (
3525 | AUnusedFlags -> false
3528 let nr_args = List.length args in
3531 pr " rb_define_method (c_hivex, \"%s\",\n" name;
3532 pr " ruby_hivex_%s, %d);\n" name (nr_args-1)
3533 | args -> (* class function *)
3534 pr " rb_define_module_function (m_hivex, \"%s\",\n" name;
3535 pr " ruby_hivex_%s, %d);\n" name nr_args
3540 let output_to filename k =
3541 let filename_new = filename ^ ".new" in
3542 chan := open_out filename_new;
3545 chan := Pervasives.stdout;
3547 (* Is the new file different from the current file? *)
3548 if Sys.file_exists filename && files_equal filename filename_new then
3549 unlink filename_new (* same, so skip it *)
3551 (* different, overwrite old one *)
3552 (try chmod filename 0o644 with Unix_error _ -> ());
3553 rename filename_new filename;
3554 chmod filename 0o444;
3555 printf "written %s\n%!" filename;
3558 let perror msg = function
3559 | Unix_error (err, _, _) ->
3560 eprintf "%s: %s\n" msg (error_message err)
3562 eprintf "%s: %s\n" msg (Printexc.to_string exn)
3567 try openfile "configure.ac" [O_RDWR] 0
3569 | Unix_error (ENOENT, _, _) ->
3571 You are probably running this from the wrong directory.
3572 Run it from the top source directory using the command
3573 generator/generator.ml
3577 perror "open: configure.ac" exn;
3580 (* Acquire a lock so parallel builds won't try to run the generator
3581 * twice at the same time. Subsequent builds will wait for the first
3582 * one to finish. Note the lock is released implicitly when the
3585 (try lockf lock_fd F_LOCK 1
3587 perror "lock: configure.ac" exn;
3592 output_to "lib/hivex.h" generate_c_header;
3593 output_to "lib/hivex.pod" generate_c_pod;
3595 output_to "lib/hivex.syms" generate_linker_script;
3597 output_to "ocaml/hivex.mli" generate_ocaml_interface;
3598 output_to "ocaml/hivex.ml" generate_ocaml_implementation;
3599 output_to "ocaml/hivex_c.c" generate_ocaml_c;
3601 output_to "perl/lib/Win/Hivex.pm" generate_perl_pm;
3602 output_to "perl/Hivex.xs" generate_perl_xs;
3604 output_to "python/hivex.py" generate_python_py;
3605 output_to "python/hivex-py.c" generate_python_c;
3607 output_to "ruby/ext/hivex/_hivex.c" generate_ruby_c;
3609 (* Always generate this file last, and unconditionally. It's used
3610 * by the Makefile to know when we must re-run the generator.
3612 let chan = open_out "generator/stamp-generator" in
3616 printf "generated %d lines of code\n" !lines