b6fb8b3af52793af32a96c7daa9a865c8f3a0d60
[hivex.git] / generator / generator.ml
1 #!/usr/bin/env ocaml
2 (* hivex
3  * Copyright (C) 2009-2011 Red Hat Inc.
4  *
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.
9  *
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.
14  *
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
18  *)
19
20 (* This script generates language bindings and some documentation for
21  * hivex.
22  *
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_
27  * directory.
28  *
29  * IMPORTANT: This script should NOT print any warnings.  If it prints
30  * warnings, you should treat them as errors.
31  *
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/
35  *)
36
37 #load "unix.cma";;
38 #load "str.cma";;
39
40 open Unix
41 open Printf
42
43 type style = ret * args
44 and ret =
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. *)
60
61 and args = argt list                    (* List of parameters. *)
62
63 and argt =                              (* Note, cannot be NULL/0 unless it
64                                            says so explicitly below. *)
65   | AHive                               (* hive_h* *)
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. *)
74
75 (* Hive types, from:
76  * https://secure.wikimedia.org/wikipedia/en/wiki/Windows_Registry#Keys_and_values
77  *
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.
81  *)
82 let hive_types = [
83   0, "none", "NONE",
84     "Just a key without a value";
85   1, "string", "SZ",
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",
90     "A blob of binary";
91   4, "dword", "DWORD",
92     "DWORD (32 bit integer), little endian";
93   5, "dword_be", "DWORD_BIG_ENDIAN",
94     "DWORD (32 bit integer), big endian";
95   6, "link", "LINK",
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",
100     "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"
107 ]
108 let max_hive_type = 11
109
110 (* Open flags (bitmask passed to AOpenFlags) *)
111 let open_flags = [
112   1, "VERBOSE", "Verbose messages";
113   2, "DEBUG", "Debug messages";
114   4, "WRITE", "Enable writes to the hive";
115 ]
116
117 (* The API calls. *)
118 let functions = [
119   "open", (RHive, [AString "filename"; AOpenFlags]),
120     "open a hive file",
121     "\
122 Opens the hive named C<filename> for reading.
123
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:
126
127 =over 4
128
129 =item HIVEX_OPEN_VERBOSE
130
131 Verbose messages.
132
133 =item HIVEX_OPEN_DEBUG
134
135 Very verbose messages, suitable for debugging problems in the library
136 itself.
137
138 This is also selected if the C<HIVEX_DEBUG> environment variable
139 is set to 1.
140
141 =item HIVEX_OPEN_WRITE
142
143 Open the hive for writing.  If omitted, the hive is read-only.
144
145 See L<hivex(3)/WRITING TO HIVE FILES>.
146
147 =back";
148
149   "close", (RErrDispose, [AHive]),
150     "close a hive handle",
151     "\
152 Close a hive handle and free all associated resources.
153
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>.";
156
157   "root", (RNode, [AHive]),
158     "return the root node of the hive",
159     "\
160 Return root node of the hive.  All valid hives must contain a root node.";
161
162   "last_modified", (RInt64, [AHive]),
163     "return the modification time from the header of the hive",
164     "\
165 Return the modification time from the header of the hive.
166
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>";
170
171   "node_name", (RString, [AHive; ANode "node"]),
172     "return the name of the node",
173     "\
174 Return the name of the node.
175
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.";
182
183   "node_timestamp", (RInt64, [AHive; ANode "node"]),
184     "return the modification time of the node",
185     "\
186 Return the modification time of the node.
187
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>";
191
192   "node_children", (RNodeList, [AHive; ANode "node"]),
193     "return children of node",
194     "\
195 Return an array of nodes which are the subkeys
196 (children) of C<node>.";
197
198   "node_get_child", (RNodeNotFound, [AHive; ANode "node"; AString "name"]),
199     "return named child of node",
200     "\
201 Return the child of node with the name C<name>, if it exists.
202
203 The name is matched case insensitively.";
204
205   "node_parent", (RNode, [AHive; ANode "node"]),
206     "return the parent of node",
207     "\
208 Return the parent of C<node>.
209
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.";
213
214   "node_values", (RValueList, [AHive; ANode "node"]),
215     "return (key, value) pairs attached to a node",
216     "\
217 Return the array of (key, value) pairs attached to this node.";
218
219   "node_get_value", (RValue, [AHive; ANode "node"; AString "key"]),
220     "return named key at node",
221     "\
222 Return the value attached to this node which has the name C<key>,
223 if it exists.
224
225 The key name is matched case insensitively.
226
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
230 default key.";
231
232   "value_key_len", (RSize, [AHive; AValue "val"]),
233     "return the length of a value's key",
234     "\
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
237 to check for errors.
238
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<\"@\">.";
242
243   "value_key", (RString, [AHive; AValue "val"]),
244     "return the key of a (key, value) pair",
245     "\
246 Return the key (name) of a (key, value) pair.  The name
247 is reencoded as UTF-8 and returned as a string.
248
249 The string should be freed by the caller when it is no longer needed.
250
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
254 as C<\"@\">.";
255
256   "value_type", (RLenType, [AHive; AValue "val"]),
257     "return data length and data type of a value",
258     "\
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.";
264
265   "node_struct_length", (RSize, [AHive; ANode "node"]),
266     "return the length of a node",
267     "\
268 Return the length of the node data structure.  Returns 0
269 and sets errno on error.";
270
271   "value_struct_length", (RSize, [AHive; AValue "val"]),
272     "return the length of a value data structure",
273     "\
274 Return the length of the value data structure.  Returns 0
275 and sets errno on error.";
276
277   "value_value", (RLenTypeVal, [AHive; AValue "val"]),
278     "return data length, data type and data of a value",
279     "\
280 Return the value of this (key, value) pair.  The value should
281 be interpreted according to its type (see C<hive_type>).";
282
283   "value_string", (RString, [AHive; AValue "val"]),
284     "return value as a string",
285     "\
286 If this value is a string, return the string reencoded as UTF-8
287 (as a C string).  This only works for values which have type
288 C<hive_t_string>, C<hive_t_expand_string> or C<hive_t_link>.";
289
290   "value_multiple_strings", (RStringList, [AHive; AValue "val"]),
291     "return value as multiple strings",
292     "\
293 If this value is a multiple-string, return the strings reencoded
294 as UTF-8 (in C, as a NULL-terminated array of C strings, in other
295 language bindings, as a list of strings).  This only
296 works for values which have type C<hive_t_multiple_strings>.";
297
298   "value_dword", (RInt32, [AHive; AValue "val"]),
299     "return value as a DWORD",
300     "\
301 If this value is a DWORD (Windows int32), return it.  This only works
302 for values which have type C<hive_t_dword> or C<hive_t_dword_be>.";
303
304   "value_qword", (RInt64, [AHive; AValue "val"]),
305     "return value as a QWORD",
306     "\
307 If this value is a QWORD (Windows int64), return it.  This only
308 works for values which have type C<hive_t_qword>.";
309
310   "commit", (RErr, [AHive; AStringNullable "filename"; AUnusedFlags]),
311     "commit (write) changes to file",
312     "\
313 Commit (write) any changes which have been made.
314
315 C<filename> is the new file to write.  If C<filename> is null/undefined
316 then we overwrite the original file (ie. the file name that was passed to
317 C<hivex_open>).
318
319 Note this does not close the hive handle.  You can perform further
320 operations on the hive after committing, including making more
321 modifications.  If you no longer wish to use the hive, then you
322 should close the handle after committing.";
323
324   "node_add_child", (RNode, [AHive; ANode "parent"; AString "name"]),
325     "add child node",
326     "\
327 Add a new child node named C<name> to the existing node C<parent>.
328 The new child initially has no subnodes and contains no keys or
329 values.  The sk-record (security descriptor) is inherited from
330 the parent.
331
332 The parent must not have an existing child called C<name>, so if you
333 want to overwrite an existing child, call C<hivex_node_delete_child>
334 first.";
335
336   "node_delete_child", (RErr, [AHive; ANode "node"]),
337     "delete child node",
338     "\
339 Delete the node C<node>.  All values at the node and all subnodes are
340 deleted (recursively).  The C<node> handle and the handles of all
341 subnodes become invalid.  You cannot delete the root node.";
342
343   "node_set_values", (RErr, [AHive; ANode "node"; ASetValues; AUnusedFlags]),
344     "set (key, value) pairs at a node",
345     "\
346 This call can be used to set all the (key, value) pairs
347 stored in C<node>.
348
349 C<node> is the node to modify.";
350
351   "node_set_value", (RErr, [AHive; ANode "node"; ASetValue; AUnusedFlags]),
352     "set a single (key, value) pair at a given node",
353     "\
354 This call can be used to replace a single C<(key, value)> pair
355 stored in C<node>.  If the key does not already exist, then a
356 new key is added.  Key matching is case insensitive.
357
358 C<node> is the node to modify.";
359 ]
360
361 (* Useful functions.
362  * Note we don't want to use any external OCaml libraries which
363  * makes this a bit harder than it should be.
364  *)
365 module StringMap = Map.Make (String)
366
367 let failwithf fs = ksprintf failwith fs
368
369 let unique = let i = ref 0 in fun () -> incr i; !i
370
371 let replace_char s c1 c2 =
372   let s2 = String.copy s in
373   let r = ref false in
374   for i = 0 to String.length s2 - 1 do
375     if String.unsafe_get s2 i = c1 then (
376       String.unsafe_set s2 i c2;
377       r := true
378     )
379   done;
380   if not !r then s else s2
381
382 let isspace c =
383   c = ' '
384   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
385
386 let triml ?(test = isspace) str =
387   let i = ref 0 in
388   let n = ref (String.length str) in
389   while !n > 0 && test str.[!i]; do
390     decr n;
391     incr i
392   done;
393   if !i = 0 then str
394   else String.sub str !i !n
395
396 let trimr ?(test = isspace) str =
397   let n = ref (String.length str) in
398   while !n > 0 && test str.[!n-1]; do
399     decr n
400   done;
401   if !n = String.length str then str
402   else String.sub str 0 !n
403
404 let trim ?(test = isspace) str =
405   trimr ~test (triml ~test str)
406
407 (* Used to memoize the result of pod2text. *)
408 let pod2text_memo_filename = "generator/.pod2text.data.version.2"
409 let pod2text_memo : ((int option * bool * bool * string * string), string list) Hashtbl.t =
410   try
411     let chan = open_in pod2text_memo_filename in
412     let v = input_value chan in
413     close_in chan;
414     v
415   with
416     _ -> Hashtbl.create 13
417 let pod2text_memo_updated () =
418   let chan = open_out pod2text_memo_filename in
419   output_value chan pod2text_memo;
420   close_out chan
421
422 (* Useful if you need the longdesc POD text as plain text.  Returns a
423  * list of lines.
424  *
425  * Because this is very slow (the slowest part of autogeneration),
426  * we memoize the results.
427  *)
428 let pod2text ?width ?(trim = true) ?(discard = true) name longdesc =
429   let key = width, trim, discard, name, longdesc in
430   try Hashtbl.find pod2text_memo key
431   with Not_found ->
432     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
433     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
434     close_out chan;
435     let cmd =
436       match width with
437       | Some width ->
438           sprintf "pod2text -w %d %s" width (Filename.quote filename)
439       | None ->
440           sprintf "pod2text %s" (Filename.quote filename) in
441     let chan = open_process_in cmd in
442     let lines = ref [] in
443     let rec loop i =
444       let line = input_line chan in
445       if i = 1 && discard then  (* discard the first line of output *)
446         loop (i+1)
447       else (
448         let line = if trim then triml line else line in
449         lines := line :: !lines;
450         loop (i+1)
451       ) in
452     let lines = try loop 1 with End_of_file -> List.rev !lines in
453     unlink filename;
454     (match close_process_in chan with
455      | WEXITED 0 -> ()
456      | WEXITED i ->
457          failwithf "pod2text: process exited with non-zero status (%d)" i
458      | WSIGNALED i | WSTOPPED i ->
459          failwithf "pod2text: process signalled or stopped by signal %d" i
460     );
461     Hashtbl.add pod2text_memo key lines;
462     pod2text_memo_updated ();
463     lines
464
465 let rec find s sub =
466   let len = String.length s in
467   let sublen = String.length sub in
468   let rec loop i =
469     if i <= len-sublen then (
470       let rec loop2 j =
471         if j < sublen then (
472           if s.[i+j] = sub.[j] then loop2 (j+1)
473           else -1
474         ) else
475           i (* found *)
476       in
477       let r = loop2 0 in
478       if r = -1 then loop (i+1) else r
479     ) else
480       -1 (* not found *)
481   in
482   loop 0
483
484 let rec replace_str s s1 s2 =
485   let len = String.length s in
486   let sublen = String.length s1 in
487   let i = find s s1 in
488   if i = -1 then s
489   else (
490     let s' = String.sub s 0 i in
491     let s'' = String.sub s (i+sublen) (len-i-sublen) in
492     s' ^ s2 ^ replace_str s'' s1 s2
493   )
494
495 let rec string_split sep str =
496   let len = String.length str in
497   let seplen = String.length sep in
498   let i = find str sep in
499   if i = -1 then [str]
500   else (
501     let s' = String.sub str 0 i in
502     let s'' = String.sub str (i+seplen) (len-i-seplen) in
503     s' :: string_split sep s''
504   )
505
506 let files_equal n1 n2 =
507   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
508   match Sys.command cmd with
509   | 0 -> true
510   | 1 -> false
511   | i -> failwithf "%s: failed with error code %d" cmd i
512
513 let rec filter_map f = function
514   | [] -> []
515   | x :: xs ->
516       match f x with
517       | Some y -> y :: filter_map f xs
518       | None -> filter_map f xs
519
520 let rec find_map f = function
521   | [] -> raise Not_found
522   | x :: xs ->
523       match f x with
524       | Some y -> y
525       | None -> find_map f xs
526
527 let iteri f xs =
528   let rec loop i = function
529     | [] -> ()
530     | x :: xs -> f i x; loop (i+1) xs
531   in
532   loop 0 xs
533
534 let mapi f xs =
535   let rec loop i = function
536     | [] -> []
537     | x :: xs -> let r = f i x in r :: loop (i+1) xs
538   in
539   loop 0 xs
540
541 let count_chars c str =
542   let count = ref 0 in
543   for i = 0 to String.length str - 1 do
544     if c = String.unsafe_get str i then incr count
545   done;
546   !count
547
548 let name_of_argt = function
549   | AHive -> "h"
550   | ANode n | AValue n | AString n | AStringNullable n -> n
551   | AOpenFlags | AUnusedFlags -> "flags"
552   | ASetValues -> "values"
553   | ASetValue -> "val"
554
555 (* Check function names etc. for consistency. *)
556 let check_functions () =
557   let contains_uppercase str =
558     let len = String.length str in
559     let rec loop i =
560       if i >= len then false
561       else (
562         let c = str.[i] in
563         if c >= 'A' && c <= 'Z' then true
564         else loop (i+1)
565       )
566     in
567     loop 0
568   in
569
570   (* Check function names. *)
571   List.iter (
572     fun (name, _, _, _) ->
573       if String.length name >= 7 && String.sub name 0 7 = "hivex" then
574         failwithf "function name %s does not need 'hivex' prefix" name;
575       if name = "" then
576         failwithf "function name is empty";
577       if name.[0] < 'a' || name.[0] > 'z' then
578         failwithf "function name %s must start with lowercase a-z" name;
579       if String.contains name '-' then
580         failwithf "function name %s should not contain '-', use '_' instead."
581           name
582   ) functions;
583
584   (* Check function parameter/return names. *)
585   List.iter (
586     fun (name, style, _, _) ->
587       let check_arg_ret_name n =
588         if contains_uppercase n then
589           failwithf "%s param/ret %s should not contain uppercase chars"
590             name n;
591         if String.contains n '-' || String.contains n '_' then
592           failwithf "%s param/ret %s should not contain '-' or '_'"
593             name n;
594         if n = "value" then
595           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;
596         if n = "int" || n = "char" || n = "short" || n = "long" then
597           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
598         if n = "i" || n = "n" then
599           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
600         if n = "argv" || n = "args" then
601           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
602
603         (* List Haskell, OCaml and C keywords here.
604          * http://www.haskell.org/haskellwiki/Keywords
605          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
606          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
607          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
608          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
609          * Omitting _-containing words, since they're handled above.
610          * Omitting the OCaml reserved word, "val", is ok,
611          * and saves us from renaming several parameters.
612          *)
613         let reserved = [
614           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
615           "char"; "class"; "const"; "constraint"; "continue"; "data";
616           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
617           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
618           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
619           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
620           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
621           "interface";
622           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
623           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
624           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
625           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
626           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
627           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
628           "volatile"; "when"; "where"; "while";
629           ] in
630         if List.mem n reserved then
631           failwithf "%s has param/ret using reserved word %s" name n;
632       in
633
634       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
635   ) functions;
636
637   (* Check short descriptions. *)
638   List.iter (
639     fun (name, _, shortdesc, _) ->
640       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
641         failwithf "short description of %s should begin with lowercase." name;
642       let c = shortdesc.[String.length shortdesc-1] in
643       if c = '\n' || c = '.' then
644         failwithf "short description of %s should not end with . or \\n." name
645   ) functions;
646
647   (* Check long dscriptions. *)
648   List.iter (
649     fun (name, _, _, longdesc) ->
650       if longdesc.[String.length longdesc-1] = '\n' then
651         failwithf "long description of %s should not end with \\n." name
652   ) functions
653
654 (* 'pr' prints to the current output file. *)
655 let chan = ref Pervasives.stdout
656 let lines = ref 0
657 let pr fs =
658   ksprintf
659     (fun str ->
660        let i = count_chars '\n' str in
661        lines := !lines + i;
662        output_string !chan str
663     ) fs
664
665 let copyright_years =
666   let this_year = 1900 + (localtime (time ())).tm_year in
667   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
668
669 (* Generate a header block in a number of standard styles. *)
670 type comment_style =
671   | CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
672   | PODCommentStyle
673 type license = GPLv2plus | LGPLv2plus | GPLv2 | LGPLv2
674
675 let generate_header ?(extra_inputs = []) comment license =
676   let inputs = "generator/generator.ml" :: extra_inputs in
677   let c = match comment with
678     | CStyle ->         pr "/* "; " *"
679     | CPlusPlusStyle -> pr "// "; "//"
680     | HashStyle ->      pr "# ";  "#"
681     | OCamlStyle ->     pr "(* "; " *"
682     | HaskellStyle ->   pr "{- "; "  "
683     | PODCommentStyle -> pr "=begin comment\n\n "; "" in
684   pr "hivex generated file\n";
685   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
686   List.iter (pr "%s   %s\n" c) inputs;
687   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
688   pr "%s\n" c;
689   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
690   pr "%s Derived from code by Petter Nordahl-Hagen under a compatible license:\n" c;
691   pr "%s   Copyright (c) 1997-2007 Petter Nordahl-Hagen.\n" c;
692   pr "%s Derived from code by Markus Stephany under a compatible license:\n" c;
693   pr "%s   Copyright (c)2000-2004, Markus Stephany.\n" c;
694   pr "%s\n" c;
695   (match license with
696    | GPLv2plus ->
697        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
698        pr "%s it under the terms of the GNU General Public License as published by\n" c;
699        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
700        pr "%s (at your option) any later version.\n" c;
701        pr "%s\n" c;
702        pr "%s This program is distributed in the hope that it will be useful,\n" c;
703        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
704        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
705        pr "%s GNU General Public License for more details.\n" c;
706        pr "%s\n" c;
707        pr "%s You should have received a copy of the GNU General Public License along\n" c;
708        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
709        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
710
711    | LGPLv2plus ->
712        pr "%s This library is free software; you can redistribute it and/or\n" c;
713        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
714        pr "%s License as published by the Free Software Foundation; either\n" c;
715        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
716        pr "%s\n" c;
717        pr "%s This library is distributed in the hope that it will be useful,\n" c;
718        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
719        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
720        pr "%s Lesser General Public License for more details.\n" c;
721        pr "%s\n" c;
722        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
723        pr "%s License along with this library; if not, write to the Free Software\n" c;
724        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
725
726    | GPLv2 ->
727        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
728        pr "%s it under the terms of the GNU General Public License as published by\n" c;
729        pr "%s the Free Software Foundation; version 2 of the License only.\n" c;
730        pr "%s\n" c;
731        pr "%s This program is distributed in the hope that it will be useful,\n" c;
732        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
733        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
734        pr "%s GNU General Public License for more details.\n" c;
735        pr "%s\n" c;
736        pr "%s You should have received a copy of the GNU General Public License along\n" c;
737        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
738        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
739
740    | LGPLv2 ->
741        pr "%s This library is free software; you can redistribute it and/or\n" c;
742        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
743        pr "%s License as published by the Free Software Foundation;\n" c;
744        pr "%s version 2.1 of the License only.\n" c;
745        pr "%s\n" c;
746        pr "%s This library is distributed in the hope that it will be useful,\n" c;
747        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
748        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
749        pr "%s Lesser General Public License for more details.\n" c;
750        pr "%s\n" c;
751        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
752        pr "%s License along with this library; if not, write to the Free Software\n" c;
753        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
754   );
755   (match comment with
756    | CStyle -> pr " */\n"
757    | CPlusPlusStyle
758    | HashStyle -> ()
759    | OCamlStyle -> pr " *)\n"
760    | HaskellStyle -> pr "-}\n"
761    | PODCommentStyle -> pr "\n=end comment\n"
762   );
763   pr "\n"
764
765 (* Start of main code generation functions below this line. *)
766
767 let rec generate_c_header () =
768   generate_header CStyle LGPLv2;
769
770   pr "\
771 #ifndef HIVEX_H_
772 #define HIVEX_H_
773
774 #include <stdlib.h>
775 #include <stdint.h>
776
777 #ifdef __cplusplus
778 extern \"C\" {
779 #endif
780
781 /* NOTE: This API is documented in the man page hivex(3). */
782
783 /* Hive handle. */
784 typedef struct hive_h hive_h;
785
786 /* Nodes and values. */
787 typedef size_t hive_node_h;
788 typedef size_t hive_value_h;
789
790 #include <errno.h>
791 #ifdef ENOKEY
792 # define HIVEX_NO_KEY ENOKEY
793 #else
794 # define HIVEX_NO_KEY ENOENT
795 #endif
796
797 /* Pre-defined types. */
798 enum hive_type {
799 ";
800   List.iter (
801     fun (t, old_style, new_style, description) ->
802       pr "  /* %s */\n" description;
803       pr "  hive_t_REG_%s,\n" new_style;
804       pr "#define hive_t_%s hive_t_REG_%s\n" old_style new_style;
805       pr "\n"
806   ) hive_types;
807   pr "\
808 };
809
810 typedef enum hive_type hive_type;
811
812 /* Bitmask of flags passed to hivex_open. */
813 ";
814   List.iter (
815     fun (v, flag, description) ->
816       pr "  /* %s */\n" description;
817       pr "#define HIVEX_OPEN_%-10s %d\n" flag v;
818   ) open_flags;
819   pr "\n";
820
821   pr "\
822 /* Array of (key, value) pairs passed to hivex_node_set_values. */
823 struct hive_set_value {
824   char *key;
825   hive_type t;
826   size_t len;
827   char *value;
828 };
829 typedef struct hive_set_value hive_set_value;
830
831 ";
832
833   pr "/* Functions. */\n";
834
835   (* Function declarations. *)
836   List.iter (
837     fun (shortname, style, _, _) ->
838       let name = "hivex_" ^ shortname in
839       generate_c_prototype ~extern:true name style
840   ) functions;
841
842   (* The visitor pattern. *)
843   pr "
844 /* Visit all nodes.  This is specific to the C API and is not made
845  * available to other languages.  This is because of the complexity
846  * of binding callbacks in other languages, but also because other
847  * languages make it much simpler to iterate over a tree.
848  */
849 struct hivex_visitor {
850   int (*node_start) (hive_h *, void *opaque, hive_node_h, const char *name);
851   int (*node_end) (hive_h *, void *opaque, hive_node_h, const char *name);
852   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);
853   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);
854   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);
855   int (*value_dword) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, int32_t);
856   int (*value_qword) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, int64_t);
857   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);
858   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);
859   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);
860   int (*value_any) (hive_h *, void *opaque, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *value);
861 };
862
863 #define HIVEX_VISIT_SKIP_BAD 1
864
865 extern int hivex_visit (hive_h *h, const struct hivex_visitor *visitor, size_t len, void *opaque, int flags);
866 extern int hivex_visit_node (hive_h *h, hive_node_h node, const struct hivex_visitor *visitor, size_t len, void *opaque, int flags);
867
868 ";
869
870   (* Finish the header file. *)
871   pr "\
872 #ifdef __cplusplus
873 }
874 #endif
875
876 #endif /* HIVEX_H_ */
877 "
878
879 and generate_c_prototype ?(extern = false) name style =
880   if extern then pr "extern ";
881   (match fst style with
882    | RErr -> pr "int "
883    | RErrDispose -> pr "int "
884    | RHive -> pr "hive_h *"
885    | RSize -> pr "size_t "
886    | RNode -> pr "hive_node_h "
887    | RNodeNotFound -> pr "hive_node_h "
888    | RNodeList -> pr "hive_node_h *"
889    | RValue -> pr "hive_value_h "
890    | RValueList -> pr "hive_value_h *"
891    | RString -> pr "char *"
892    | RStringList -> pr "char **"
893    | RLenType -> pr "int "
894    | RLenTypeVal -> pr "char *"
895    | RInt32 -> pr "int32_t "
896    | RInt64 -> pr "int64_t "
897   );
898   pr "%s (" name;
899   let comma = ref false in
900   List.iter (
901     fun arg ->
902       if !comma then pr ", "; comma := true;
903       match arg with
904       | AHive -> pr "hive_h *h"
905       | ANode n -> pr "hive_node_h %s" n
906       | AValue n -> pr "hive_value_h %s" n
907       | AString n | AStringNullable n -> pr "const char *%s" n
908       | AOpenFlags | AUnusedFlags -> pr "int flags"
909       | ASetValues -> pr "size_t nr_values, const hive_set_value *values"
910       | ASetValue -> pr "const hive_set_value *val"
911   ) (snd style);
912   (match fst style with
913    | RLenType | RLenTypeVal -> pr ", hive_type *t, size_t *len"
914    | _ -> ()
915   );
916   pr ");\n"
917
918 and generate_c_pod () =
919   generate_header PODCommentStyle GPLv2;
920
921   pr "\
922   =encoding utf8
923
924 =head1 NAME
925
926 hivex - Windows Registry \"hive\" extraction library
927
928 =head1 SYNOPSIS
929
930  #include <hivex.h>
931
932 ";
933   List.iter (
934     fun (shortname, style, _, _) ->
935       let name = "hivex_" ^ shortname in
936       pr " ";
937       generate_c_prototype ~extern:false name style;
938   ) functions;
939
940   pr "\
941
942 Link with I<-lhivex>.
943
944 =head1 DESCRIPTION
945
946 Hivex is a library for extracting the contents of Windows Registry
947 \"hive\" files.  It is designed to be secure against buggy or malicious
948 registry files.
949
950 Unlike other tools in this area, it doesn't use the textual .REG
951 format, because parsing that is as much trouble as parsing the
952 original binary format.  Instead it makes the file available
953 through a C API, and then wraps this API in higher level scripting
954 and GUI tools.
955
956 There is a separate program to export the hive as XML
957 (see L<hivexml(1)>), or to navigate the file (see L<hivexsh(1)>).
958 There is also a Perl script to export and merge the
959 file as a textual .REG (regedit) file, see L<hivexregedit(1)>.
960
961 If you just want to export or modify the Registry of a Windows
962 virtual machine, you should look at L<virt-win-reg(1)>.
963
964 Hivex is also comes with language bindings for
965 OCaml, Perl, Python and Ruby.
966
967 =head1 TYPES
968
969 =head2 C<hive_h *>
970
971 This handle describes an open hive file.
972
973 =head2 C<hive_node_h>
974
975 This is a node handle, an integer but opaque outside the library.
976 Valid node handles cannot be 0.  The library returns 0 in some
977 situations to indicate an error.
978
979 =head2 C<hive_type>
980
981 The enum below describes the possible types for the value(s)
982 stored at each node.  Note that you should not trust the
983 type field in a Windows Registry, as it very often has no
984 relationship to reality.  Some applications use their own
985 types.  The encoding of strings is not specified.  Some
986 programs store everything (including strings) in binary blobs.
987
988  enum hive_type {
989 ";
990   List.iter (
991     fun (t, _, new_style, description) ->
992       pr "   /* %s */\n" description;
993       pr "   hive_t_REG_%s = %d,\n" new_style t
994   ) hive_types;
995   pr "\
996  };
997
998 =head2 C<hive_value_h>
999
1000 This is a value handle, an integer but opaque outside the library.
1001 Valid value handles cannot be 0.  The library returns 0 in some
1002 situations to indicate an error.
1003
1004 =head2 C<hive_set_value>
1005
1006 The typedef C<hive_set_value> is used in conjunction with the
1007 C<hivex_node_set_values> call described below.
1008
1009  struct hive_set_value {
1010    char *key;     /* key - a UTF-8 encoded ASCIIZ string */
1011    hive_type t;   /* type of value field */
1012    size_t len;    /* length of value field in bytes */
1013    char *value;   /* value field */
1014  };
1015  typedef struct hive_set_value hive_set_value;
1016
1017 To set the default value for a node, you have to pass C<key = \"\">.
1018
1019 Note that the C<value> field is just treated as a list of bytes, and
1020 is stored directly in the hive.  The caller has to ensure correct
1021 encoding and endianness, for example converting dwords to little
1022 endian.
1023
1024 The correct type and encoding for values depends on the node and key
1025 in the registry, the version of Windows, and sometimes even changes
1026 between versions of Windows for the same key.  We don't document it
1027 here.  Often it's not documented at all.
1028
1029 =head1 FUNCTIONS
1030
1031 ";
1032   List.iter (
1033     fun (shortname, style, _, longdesc) ->
1034       let name = "hivex_" ^ shortname in
1035       pr "=head2 %s\n" name;
1036       pr "\n ";
1037       generate_c_prototype ~extern:false name style;
1038       pr "\n";
1039       pr "%s\n" longdesc;
1040       pr "\n";
1041
1042       if List.mem AUnusedFlags (snd style) then
1043         pr "The flags parameter is unused.  Always pass 0.\n\n";
1044
1045       if List.mem ASetValues (snd style) then
1046         pr "C<values> is an array of (key, value) pairs.  There
1047 should be C<nr_values> elements in this array.
1048
1049 Any existing values stored at the node are discarded, and their
1050 C<hive_value_h> handles become invalid.  Thus you can remove all
1051 values stored at C<node> by passing C<nr_values = 0>.\n\n";
1052
1053       if List.mem ASetValue (snd style) then
1054         pr "C<value> is a single (key, value) pair.
1055
1056 Existing C<hive_value_h> handles become invalid.\n\n";
1057
1058       (match fst style with
1059        | RErr ->
1060            pr "\
1061 Returns 0 on success.
1062 On error this returns -1 and sets errno.\n\n"
1063        | RErrDispose ->
1064            pr "\
1065 Returns 0 on success.
1066 On error this returns -1 and sets errno.
1067
1068 This function frees the hive handle (even if it returns an error).
1069 The hive handle must not be used again after calling this function.\n\n"
1070        | RHive ->
1071            pr "\
1072 Returns a new hive handle.
1073 On error this returns NULL and sets errno.\n\n"
1074        | RSize ->
1075            pr "\
1076 Returns a size.
1077 On error this returns 0 and sets errno.\n\n"
1078        | RNode ->
1079            pr "\
1080 Returns a node handle.
1081 On error this returns 0 and sets errno.\n\n"
1082        | RNodeNotFound ->
1083            pr "\
1084 Returns a node handle.
1085 If the node was not found, this returns 0 without setting errno.
1086 On error this returns 0 and sets errno.\n\n"
1087        | RNodeList ->
1088            pr "\
1089 Returns a 0-terminated array of nodes.
1090 The array must be freed by the caller when it is no longer needed.
1091 On error this returns NULL and sets errno.\n\n"
1092        | RValue ->
1093            pr "\
1094 Returns a value handle.
1095 On error this returns 0 and sets errno.\n\n"
1096        | RValueList ->
1097            pr "\
1098 Returns a 0-terminated array of values.
1099 The array must be freed by the caller when it is no longer needed.
1100 On error this returns NULL and sets errno.\n\n"
1101        | RString ->
1102            pr "\
1103 Returns a string.
1104 The string must be freed by the caller when it is no longer needed.
1105 On error this returns NULL and sets errno.\n\n"
1106        | RStringList ->
1107            pr "\
1108 Returns a NULL-terminated array of C strings.
1109 The strings and the array must all be freed by the caller when
1110 they are no longer needed.
1111 On error this returns NULL and sets errno.\n\n"
1112        | RLenType ->
1113            pr "\
1114 Returns 0 on success.
1115 On error this returns -1 and sets errno.\n\n"
1116        | RLenTypeVal ->
1117            pr "\
1118 The value is returned as an array of bytes (of length C<len>).
1119 The value must be freed by the caller when it is no longer needed.
1120 On error this returns NULL and sets errno.\n\n"
1121        | RInt32 | RInt64 -> ()
1122       );
1123   ) functions;
1124
1125   pr "\
1126 =head1 WRITING TO HIVE FILES
1127
1128 The hivex library supports making limited modifications to hive files.
1129 We have tried to implement this very conservatively in order to reduce
1130 the chance of corrupting your registry.  However you should be careful
1131 and take back-ups, since Microsoft has never documented the hive
1132 format, and so it is possible there are nuances in the
1133 reverse-engineered format that we do not understand.
1134
1135 To be able to modify a hive, you must pass the C<HIVEX_OPEN_WRITE>
1136 flag to C<hivex_open>, otherwise any write operation will return with
1137 errno C<EROFS>.
1138
1139 The write operations shown below do not modify the on-disk file
1140 immediately.  You must call C<hivex_commit> in order to write the
1141 changes to disk.  If you call C<hivex_close> without committing then
1142 any writes are discarded.
1143
1144 Hive files internally consist of a \"memory dump\" of binary blocks
1145 (like the C heap), and some of these blocks can be unused.  The hivex
1146 library never reuses these unused blocks.  Instead, to ensure
1147 robustness in the face of the partially understood on-disk format,
1148 hivex only allocates new blocks after the end of the file, and makes
1149 minimal modifications to existing structures in the file to point to
1150 these new blocks.  This makes hivex slightly less disk-efficient than
1151 it could be, but disk is cheap, and registry modifications tend to be
1152 very small.
1153
1154 When deleting nodes, it is possible that this library may leave
1155 unreachable live blocks in the hive.  This is because certain parts of
1156 the hive disk format such as security (sk) records and big data (db)
1157 records and classname fields are not well understood (and not
1158 documented at all) and we play it safe by not attempting to modify
1159 them.  Apart from wasting a little bit of disk space, it is not
1160 thought that unreachable blocks are a problem.
1161
1162 =head2 WRITE OPERATIONS WHICH ARE NOT SUPPORTED
1163
1164 =over 4
1165
1166 =item *
1167
1168 Changing the root node.
1169
1170 =item *
1171
1172 Creating a new hive file from scratch.  This is impossible at present
1173 because not all fields in the header are understood.  In the hivex
1174 source tree is a file called C<images/minimal> which could be used as
1175 the basis for a new hive (but I<caveat emptor>).
1176
1177 =item *
1178
1179 Modifying or deleting single values at a node.
1180
1181 =item *
1182
1183 Modifying security key (sk) records or classnames.
1184 Previously we did not understand these records.  However now they
1185 are well-understood and we could add support if it was required
1186 (but nothing much really uses them).
1187
1188 =back
1189
1190 =head1 VISITING ALL NODES
1191
1192 The visitor pattern is useful if you want to visit all nodes
1193 in the tree or all nodes below a certain point in the tree.
1194
1195 First you set up your own C<struct hivex_visitor> with your
1196 callback functions.
1197
1198 Each of these callback functions should return 0 on success or -1
1199 on error.  If any callback returns -1, then the entire visit
1200 terminates immediately.  If you don't need a callback function at
1201 all, set the function pointer to NULL.
1202
1203  struct hivex_visitor {
1204    int (*node_start) (hive_h *, void *opaque, hive_node_h, const char *name);
1205    int (*node_end) (hive_h *, void *opaque, hive_node_h, const char *name);
1206    int (*value_string) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1207          hive_type t, size_t len, const char *key, const char *str);
1208    int (*value_multiple_strings) (hive_h *, void *opaque, hive_node_h,
1209          hive_value_h, hive_type t, size_t len, const char *key, char **argv);
1210    int (*value_string_invalid_utf16) (hive_h *, void *opaque, hive_node_h,
1211          hive_value_h, hive_type t, size_t len, const char *key,
1212          const char *str);
1213    int (*value_dword) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1214          hive_type t, size_t len, const char *key, int32_t);
1215    int (*value_qword) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1216          hive_type t, size_t len, const char *key, int64_t);
1217    int (*value_binary) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1218          hive_type t, size_t len, const char *key, const char *value);
1219    int (*value_none) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1220          hive_type t, size_t len, const char *key, const char *value);
1221    int (*value_other) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1222          hive_type t, size_t len, const char *key, const char *value);
1223    /* If value_any callback is not NULL, then the other value_*
1224     * callbacks are not used, and value_any is called on all values.
1225     */
1226    int (*value_any) (hive_h *, void *opaque, hive_node_h, hive_value_h,
1227          hive_type t, size_t len, const char *key, const char *value);
1228  };
1229
1230 =over 4
1231
1232 =item hivex_visit
1233
1234  int hivex_visit (hive_h *h, const struct hivex_visitor *visitor, size_t len, void *opaque, int flags);
1235
1236 Visit all the nodes recursively in the hive C<h>.
1237
1238 C<visitor> should be a C<hivex_visitor> structure with callback
1239 fields filled in as required (unwanted callbacks can be set to
1240 NULL).  C<len> must be the length of the 'visitor' struct (you
1241 should pass C<sizeof (struct hivex_visitor)> for this).
1242
1243 This returns 0 if the whole recursive visit was completed
1244 successfully.  On error this returns -1.  If one of the callback
1245 functions returned an error than we don't touch errno.  If the
1246 error was generated internally then we set errno.
1247
1248 You can skip bad registry entries by setting C<flag> to
1249 C<HIVEX_VISIT_SKIP_BAD>.  If this flag is not set, then a bad registry
1250 causes the function to return an error immediately.
1251
1252 This function is robust if the registry contains cycles or
1253 pointers which are invalid or outside the registry.  It detects
1254 these cases and returns an error.
1255
1256 =item hivex_visit_node
1257
1258  int hivex_visit_node (hive_h *h, hive_node_h node, const struct hivex_visitor *visitor, size_t len, void *opaque);
1259
1260 Same as C<hivex_visit> but instead of starting out at the root, this
1261 starts at C<node>.
1262
1263 =back
1264
1265 =head1 THE STRUCTURE OF THE WINDOWS REGISTRY
1266
1267 Note: To understand the relationship between hives and the common
1268 Windows Registry keys (like C<HKEY_LOCAL_MACHINE>) please see the
1269 Wikipedia page on the Windows Registry.
1270
1271 The Windows Registry is split across various binary files, each
1272 file being known as a \"hive\".  This library only handles a single
1273 hive file at a time.
1274
1275 Hives are n-ary trees with a single root.  Each node in the tree
1276 has a name.
1277
1278 Each node in the tree (including non-leaf nodes) may have an
1279 arbitrary list of (key, value) pairs attached to it.  It may
1280 be the case that one of these pairs has an empty key.  This
1281 is referred to as the default key for the node.
1282
1283 The (key, value) pairs are the place where the useful data is
1284 stored in the registry.  The key is always a string (possibly the
1285 empty string for the default key).  The value is a typed object
1286 (eg. string, int32, binary, etc.).
1287
1288 =head2 RELATIONSHIP TO .REG FILES
1289
1290 The hivex C library does not care about or deal with Windows .REG
1291 files.  Instead we push this complexity up to the Perl
1292 L<Win::Hivex(3)> library and the Perl programs
1293 L<hivexregedit(1)> and L<virt-win-reg(1)>.
1294 Nevertheless it is useful to look at the relationship between the
1295 Registry and .REG files because they are so common.
1296
1297 A .REG file is a textual representation of the registry, or part of the
1298 registry.  The actual registry hives that Windows uses are binary
1299 files.  There are a number of Windows and Linux tools that let you
1300 generate .REG files, or merge .REG files back into the registry hives.
1301 Notable amongst them is Microsoft's REGEDIT program (formerly known as
1302 REGEDT32).
1303
1304 A typical .REG file will contain many sections looking like this:
1305
1306  [HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\Stack]
1307  \"@\"=\"Generic Stack\"
1308  \"TileInfo\"=\"prop:System.FileCount\"
1309  \"TilePath\"=str(2):\"%%systemroot%%\\\\system32\"
1310  \"ThumbnailCutoff\"=dword:00000000
1311  \"FriendlyTypeName\"=hex(2):40,00,25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,\\
1312   6f,00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,\\
1313   33,00,32,00,5c,00,73,00,65,00,61,00,72,00,63,00,68,00,66,00,\\
1314   6f,00,6c,00,64,00,65,00,72,00,2e,00,64,00,6c,00,6c,00,2c,00,\\
1315   2d,00,39,00,30,00,32,00,38,00,00,00,d8
1316
1317 Taking this one piece at a time:
1318
1319  [HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\Stack]
1320
1321 This is the path to this node in the registry tree.  The first part,
1322 C<HKEY_LOCAL_MACHINE\\SOFTWARE> means that this comes from a hive
1323 file called C<C:\\WINDOWS\\SYSTEM32\\CONFIG\\SOFTWARE>.
1324 C<\\Classes\\Stack> is the real path part,
1325 starting at the root node of the C<SOFTWARE> hive.
1326
1327 Below the node name is a list of zero or more key-value pairs.  Any
1328 interior or leaf node in the registry may have key-value pairs
1329 attached.
1330
1331  \"@\"=\"Generic Stack\"
1332
1333 This is the \"default key\".  In reality (ie. inside the binary hive)
1334 the key string is the empty string.  In .REG files this is written as
1335 C<@> but this has no meaning either in the hives themselves or in this
1336 library.  The value is a string (type 1 - see C<enum hive_type>
1337 above).
1338
1339  \"TileInfo\"=\"prop:System.FileCount\"
1340
1341 This is a regular (key, value) pair, with the value being a type 1
1342 string.  Note that inside the binary file the string is likely to be
1343 UTF-16LE encoded.  This library converts to and from UTF-8 strings
1344 transparently in some cases.
1345
1346  \"TilePath\"=str(2):\"%%systemroot%%\\\\system32\"
1347
1348 The value in this case has type 2 (expanded string) meaning that some
1349 %%...%% variables get expanded by Windows.  (This library doesn't know
1350 or care about variable expansion).
1351
1352  \"ThumbnailCutoff\"=dword:00000000
1353
1354 The value in this case is a dword (type 4).
1355
1356  \"FriendlyTypeName\"=hex(2):40,00,....
1357
1358 This value is an expanded string (type 2) represented in the .REG file
1359 as a series of hex bytes.  In this case the string appears to be a
1360 UTF-16LE string.
1361
1362 =head1 NOTE ON THE USE OF ERRNO
1363
1364 Many functions in this library set errno to indicate errors.  These
1365 are the values of errno you may encounter (this list is not
1366 exhaustive):
1367
1368 =over 4
1369
1370 =item ENOTSUP
1371
1372 Corrupt or unsupported Registry file format.
1373
1374 =item HIVEX_NO_KEY
1375
1376 Missing root key.
1377
1378 =item EINVAL
1379
1380 Passed an invalid argument to the function.
1381
1382 =item EFAULT
1383
1384 Followed a Registry pointer which goes outside
1385 the registry or outside a registry block.
1386
1387 =item ELOOP
1388
1389 Registry contains cycles.
1390
1391 =item ERANGE
1392
1393 Field in the registry out of range.
1394
1395 =item EEXIST
1396
1397 Registry key already exists.
1398
1399 =item EROFS
1400
1401 Tried to write to a registry which is not opened for writing.
1402
1403 =back
1404
1405 =head1 ENVIRONMENT VARIABLES
1406
1407 =over 4
1408
1409 =item HIVEX_DEBUG
1410
1411 Setting HIVEX_DEBUG=1 will enable very verbose messages.  This is
1412 useful for debugging problems with the library itself.
1413
1414 =back
1415
1416 =head1 SEE ALSO
1417
1418 L<hivexget(1)>,
1419 L<hivexml(1)>,
1420 L<hivexsh(1)>,
1421 L<hivexregedit(1)>,
1422 L<virt-win-reg(1)>,
1423 L<Win::Hivex(3)>,
1424 L<guestfs(3)>,
1425 L<http://libguestfs.org/>,
1426 L<virt-cat(1)>,
1427 L<virt-edit(1)>,
1428 L<http://en.wikipedia.org/wiki/Windows_Registry>.
1429
1430 =head1 AUTHORS
1431
1432 Richard W.M. Jones (C<rjones at redhat dot com>)
1433
1434 =head1 COPYRIGHT
1435
1436 Copyright (C) 2009-2010 Red Hat Inc.
1437
1438 Derived from code by Petter Nordahl-Hagen under a compatible license:
1439 Copyright (C) 1997-2007 Petter Nordahl-Hagen.
1440
1441 Derived from code by Markus Stephany under a compatible license:
1442 Copyright (C) 2000-2004 Markus Stephany.
1443
1444 This library is free software; you can redistribute it and/or
1445 modify it under the terms of the GNU Lesser General Public
1446 License as published by the Free Software Foundation;
1447 version 2.1 of the License only.
1448
1449 This library is distributed in the hope that it will be useful,
1450 but WITHOUT ANY WARRANTY; without even the implied warranty of
1451 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1452 Lesser General Public License for more details.
1453 "
1454
1455 (* Generate the linker script which controls the visibility of
1456  * symbols in the public ABI and ensures no other symbols get
1457  * exported accidentally.
1458  *)
1459 and generate_linker_script () =
1460   generate_header HashStyle GPLv2plus;
1461
1462   let globals = [
1463     "hivex_visit";
1464     "hivex_visit_node"
1465   ] in
1466
1467   let functions =
1468     List.map (fun (name, _, _, _) -> "hivex_" ^ name)
1469       functions in
1470   let globals = List.sort compare (globals @ functions) in
1471
1472   pr "{\n";
1473   pr "    global:\n";
1474   List.iter (pr "        %s;\n") globals;
1475   pr "\n";
1476
1477   pr "    local:\n";
1478   pr "        *;\n";
1479   pr "};\n"
1480
1481 and generate_ocaml_interface () =
1482   generate_header OCamlStyle LGPLv2plus;
1483
1484   pr "\
1485 type t
1486 (** A [hive_h] hive file handle. *)
1487
1488 type node
1489 type value
1490 (** Nodes and values. *)
1491
1492 exception Error of string * Unix.error * string
1493 (** Error raised by a function.
1494
1495     The first parameter is the name of the function which raised the error.
1496     The second parameter is the errno (see the [Unix] module).  The third
1497     parameter is a human-readable string corresponding to the errno.
1498
1499     See hivex(3) for a partial list of interesting errno values that
1500     can be generated by the library. *)
1501 exception Handle_closed of string
1502 (** This exception is raised if you call a function on a closed handle. *)
1503
1504 type hive_type =
1505 ";
1506   iteri (
1507     fun i ->
1508       fun (t, _, new_style, description) ->
1509         assert (i = t);
1510         pr "  | REG_%s (** %s *)\n" new_style description
1511   ) hive_types;
1512
1513   pr "\
1514   | REG_UNKNOWN of int32 (** unknown type *)
1515 (** Hive type field. *)
1516
1517 type open_flag =
1518 ";
1519   iteri (
1520     fun i ->
1521       fun (v, flag, description) ->
1522         assert (1 lsl i = v);
1523         pr "  | OPEN_%s (** %s *)\n" flag description
1524   ) open_flags;
1525
1526   pr "\
1527 (** Open flags for {!open_file} call. *)
1528
1529 type set_value = {
1530   key : string;
1531   t : hive_type;
1532   value : string;
1533 }
1534 (** (key, value) pair passed (as an array) to {!node_set_values}. *)
1535 ";
1536
1537   List.iter (
1538     fun (name, style, shortdesc, _) ->
1539       pr "\n";
1540       generate_ocaml_prototype name style;
1541       pr "(** %s *)\n" shortdesc
1542   ) functions
1543
1544 and generate_ocaml_implementation () =
1545   generate_header OCamlStyle LGPLv2plus;
1546
1547   pr "\
1548 type t
1549 type node = int
1550 type value = int
1551
1552 exception Error of string * Unix.error * string
1553 exception Handle_closed of string
1554
1555 (* Give the exceptions names, so they can be raised from the C code. *)
1556 let () =
1557   Callback.register_exception \"ocaml_hivex_error\"
1558     (Error (\"\", Unix.EUNKNOWNERR 0, \"\"));
1559   Callback.register_exception \"ocaml_hivex_closed\" (Handle_closed \"\")
1560
1561 type hive_type =
1562 ";
1563   iteri (
1564     fun i ->
1565       fun (t, _, new_style, _) ->
1566         assert (i = t);
1567         pr "  | REG_%s\n" new_style
1568   ) hive_types;
1569
1570   pr "\
1571   | REG_UNKNOWN of int32
1572
1573 type open_flag =
1574 ";
1575   iteri (
1576     fun i ->
1577       fun (v, flag, description) ->
1578         assert (1 lsl i = v);
1579         pr "  | OPEN_%s (** %s *)\n" flag description
1580   ) open_flags;
1581
1582   pr "\
1583
1584 type set_value = {
1585   key : string;
1586   t : hive_type;
1587   value : string;
1588 }
1589
1590 ";
1591
1592   List.iter (
1593     fun (name, style, _, _) ->
1594       generate_ocaml_prototype ~is_external:true name style
1595   ) functions
1596
1597 and generate_ocaml_prototype ?(is_external = false) name style =
1598   let ocaml_name = if name = "open" then "open_file" else name in
1599
1600   if is_external then pr "external " else pr "val ";
1601   pr "%s : " ocaml_name;
1602   List.iter (
1603     function
1604     | AHive -> pr "t -> "
1605     | ANode _ -> pr "node -> "
1606     | AValue _ -> pr "value -> "
1607     | AString _ -> pr "string -> "
1608     | AStringNullable _ -> pr "string option -> "
1609     | AOpenFlags -> pr "open_flag list -> "
1610     | AUnusedFlags -> ()
1611     | ASetValues -> pr "set_value array -> "
1612     | ASetValue -> pr "set_value -> "
1613   ) (snd style);
1614   (match fst style with
1615    | RErr -> pr "unit" (* all errors are turned into exceptions *)
1616    | RErrDispose -> pr "unit"
1617    | RHive -> pr "t"
1618    | RSize -> pr "int64"
1619    | RNode -> pr "node"
1620    | RNodeNotFound -> pr "node"
1621    | RNodeList -> pr "node array"
1622    | RValue -> pr "value"
1623    | RValueList -> pr "value array"
1624    | RString -> pr "string"
1625    | RStringList -> pr "string array"
1626    | RLenType -> pr "hive_type * int"
1627    | RLenTypeVal -> pr "hive_type * string"
1628    | RInt32 -> pr "int32"
1629    | RInt64 -> pr "int64"
1630   );
1631   if is_external then
1632     pr " = \"ocaml_hivex_%s\"" name;
1633   pr "\n"
1634
1635 and generate_ocaml_c () =
1636   generate_header CStyle LGPLv2plus;
1637
1638   pr "\
1639 #include <config.h>
1640
1641 #include <stdio.h>
1642 #include <stdlib.h>
1643 #include <string.h>
1644 #include <stdint.h>
1645 #include <errno.h>
1646
1647 #include <caml/config.h>
1648 #include <caml/alloc.h>
1649 #include <caml/callback.h>
1650 #include <caml/custom.h>
1651 #include <caml/fail.h>
1652 #include <caml/memory.h>
1653 #include <caml/mlvalues.h>
1654 #include <caml/signals.h>
1655
1656 #ifdef HAVE_CAML_UNIXSUPPORT_H
1657 #include <caml/unixsupport.h>
1658 #else
1659 extern value unix_error_of_code (int errcode);
1660 #endif
1661
1662 #ifndef HAVE_CAML_RAISE_WITH_ARGS
1663 static void
1664 caml_raise_with_args (value tag, int nargs, value args[])
1665 {
1666   CAMLparam1 (tag);
1667   CAMLxparamN (args, nargs);
1668   value bucket;
1669   int i;
1670
1671   bucket = caml_alloc_small (1 + nargs, 0);
1672   Field(bucket, 0) = tag;
1673   for (i = 0; i < nargs; i++) Field(bucket, 1 + i) = args[i];
1674   caml_raise(bucket);
1675   CAMLnoreturn;
1676 }
1677 #endif
1678
1679 #include <hivex.h>
1680
1681 #define Hiveh_val(v) (*((hive_h **)Data_custom_val(v)))
1682 static value Val_hiveh (hive_h *);
1683 static int HiveOpenFlags_val (value);
1684 static hive_set_value *HiveSetValue_val (value);
1685 static hive_set_value *HiveSetValues_val (value);
1686 static hive_type HiveType_val (value);
1687 static value Val_hive_type (hive_type);
1688 static value copy_int_array (size_t *);
1689 static value copy_type_len (size_t, hive_type);
1690 static value copy_type_value (const char *, size_t, hive_type);
1691 static void raise_error (const char *) Noreturn;
1692 static void raise_closed (const char *) Noreturn;
1693
1694 ";
1695
1696   (* The wrappers. *)
1697   List.iter (
1698     fun (name, style, _, _) ->
1699       pr "/* Automatically generated wrapper for function\n";
1700       pr " * "; generate_ocaml_prototype name style;
1701       pr " */\n";
1702       pr "\n";
1703
1704       let c_params =
1705         List.map (function
1706                   | ASetValues -> ["nrvalues"; "values"]
1707                   | AUnusedFlags -> ["0"]
1708                   | arg -> [name_of_argt arg]) (snd style) in
1709       let c_params =
1710         match fst style with
1711         | RLenType | RLenTypeVal -> c_params @ [["&t"; "&len"]]
1712         | _ -> c_params in
1713       let c_params = List.concat c_params in
1714
1715       let params =
1716         filter_map (function
1717                     | AUnusedFlags -> None
1718                     | arg -> Some (name_of_argt arg ^ "v")) (snd style) in
1719
1720       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
1721       pr "CAMLprim value ocaml_hivex_%s (value %s" name (List.hd params);
1722       List.iter (pr ", value %s") (List.tl params); pr ");\n";
1723       pr "\n";
1724
1725       pr "CAMLprim value\n";
1726       pr "ocaml_hivex_%s (value %s" name (List.hd params);
1727       List.iter (pr ", value %s") (List.tl params);
1728       pr ")\n";
1729       pr "{\n";
1730
1731       pr "  CAMLparam%d (%s);\n"
1732         (List.length params) (String.concat ", " params);
1733       pr "  CAMLlocal1 (rv);\n";
1734       pr "\n";
1735
1736       List.iter (
1737         function
1738         | AHive ->
1739             pr "  hive_h *h = Hiveh_val (hv);\n";
1740             pr "  if (h == NULL)\n";
1741             pr "    raise_closed (\"%s\");\n" name
1742         | ANode n ->
1743             pr "  hive_node_h %s = Int_val (%sv);\n" n n
1744         | AValue n ->
1745             pr "  hive_value_h %s = Int_val (%sv);\n" n n
1746         | AString n ->
1747             pr "  const char *%s = String_val (%sv);\n" n n
1748         | AStringNullable n ->
1749             pr "  const char *%s =\n" n;
1750             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
1751               n n
1752         | AOpenFlags ->
1753             pr "  int flags = HiveOpenFlags_val (flagsv);\n"
1754         | AUnusedFlags -> ()
1755         | ASetValues ->
1756             pr "  int nrvalues = Wosize_val (valuesv);\n";
1757             pr "  hive_set_value *values = HiveSetValues_val (valuesv);\n"
1758         | ASetValue ->
1759             pr "  hive_set_value *val = HiveSetValue_val (valv);\n"
1760       ) (snd style);
1761       pr "\n";
1762
1763       let error_code =
1764         match fst style with
1765         | RErr -> pr "  int r;\n"; "-1"
1766         | RErrDispose -> pr "  int r;\n"; "-1"
1767         | RHive -> pr "  hive_h *r;\n"; "NULL"
1768         | RSize -> pr "  size_t r;\n"; "0"
1769         | RNode -> pr "  hive_node_h r;\n"; "0"
1770         | RNodeNotFound ->
1771             pr "  errno = 0;\n";
1772             pr "  hive_node_h r;\n";
1773             "0 && errno != 0"
1774         | RNodeList -> pr "  hive_node_h *r;\n"; "NULL"
1775         | RValue -> pr "  hive_value_h r;\n"; "0"
1776         | RValueList -> pr "  hive_value_h *r;\n"; "NULL"
1777         | RString -> pr "  char *r;\n"; "NULL"
1778         | RStringList -> pr "  char **r;\n"; "NULL"
1779         | RLenType ->
1780             pr "  int r;\n";
1781             pr "  size_t len;\n";
1782             pr "  hive_type t;\n";
1783             "-1"
1784         | RLenTypeVal ->
1785             pr "  char *r;\n";
1786             pr "  size_t len;\n";
1787             pr "  hive_type t;\n";
1788             "NULL"
1789         | RInt32 ->
1790             pr "  errno = 0;\n";
1791             pr "  int32_t r;\n";
1792             "-1 && errno != 0"
1793         | RInt64 ->
1794             pr "  errno = 0;\n";
1795             pr "  int64_t r;\n";
1796             "-1 && errno != 0" in
1797
1798       (* The libguestfs OCaml bindings call enter_blocking_section
1799        * here.  However I don't think that is safe, because we are
1800        * holding pointers to caml strings during the call, and these
1801        * could be moved or freed by other threads.  In any case, there
1802        * is very little reason to enter_blocking_section for any hivex
1803        * call, so don't do it.  XXX
1804        *)
1805       (*pr "  caml_enter_blocking_section ();\n";*)
1806       pr "  r = hivex_%s (%s" name (List.hd c_params);
1807       List.iter (pr ", %s") (List.tl c_params);
1808       pr ");\n";
1809       (*pr "  caml_leave_blocking_section ();\n";*)
1810       pr "\n";
1811
1812       (* Dispose of the hive handle (even if hivex_close returns error). *)
1813       (match fst style with
1814        | RErrDispose ->
1815            pr "  /* So we don't double-free in the finalizer. */\n";
1816            pr "  Hiveh_val (hv) = NULL;\n";
1817            pr "\n";
1818        | _ -> ()
1819       );
1820
1821       List.iter (
1822         function
1823         | AHive | ANode _ | AValue _ | AString _ | AStringNullable _
1824         | AOpenFlags | AUnusedFlags -> ()
1825         | ASetValues ->
1826             pr "  free (values);\n";
1827             pr "\n";
1828         | ASetValue ->
1829             pr "  free (val);\n";
1830             pr "\n";
1831       ) (snd style);
1832
1833       (* Check for errors. *)
1834       pr "  if (r == %s)\n" error_code;
1835       pr "    raise_error (\"%s\");\n" name;
1836       pr "\n";
1837
1838       (match fst style with
1839        | RErr -> pr "  rv = Val_unit;\n"
1840        | RErrDispose -> pr "  rv = Val_unit;\n"
1841        | RHive -> pr "  rv = Val_hiveh (r);\n"
1842        | RSize -> pr "  rv = caml_copy_int64 (r);\n"
1843        | RNode -> pr "  rv = Val_int (r);\n"
1844        | RNodeNotFound ->
1845            pr "  if (r == 0)\n";
1846            pr "    caml_raise_not_found ();\n";
1847            pr "\n";
1848            pr "  rv = Val_int (r);\n"
1849        | RNodeList ->
1850            pr "  rv = copy_int_array (r);\n";
1851            pr "  free (r);\n"
1852        | RValue -> pr "  rv = Val_int (r);\n"
1853        | RValueList ->
1854            pr "  rv = copy_int_array (r);\n";
1855            pr "  free (r);\n"
1856        | RString ->
1857            pr "  rv = caml_copy_string (r);\n";
1858            pr "  free (r);\n"
1859        | RStringList ->
1860            pr "  rv = caml_copy_string_array ((const char **) r);\n";
1861            pr "  for (int i = 0; r[i] != NULL; ++i) free (r[i]);\n";
1862            pr "  free (r);\n"
1863        | RLenType -> pr "  rv = copy_type_len (len, t);\n"
1864        | RLenTypeVal ->
1865            pr "  rv = copy_type_value (r, len, t);\n";
1866            pr "  free (r);\n"
1867        | RInt32 -> pr "  rv = caml_copy_int32 (r);\n"
1868        | RInt64 -> pr "  rv = caml_copy_int64 (r);\n"
1869       );
1870
1871       pr "  CAMLreturn (rv);\n";
1872       pr "}\n";
1873       pr "\n";
1874
1875   ) functions;
1876
1877   pr "\
1878 static int
1879 HiveOpenFlags_val (value v)
1880 {
1881   int flags = 0;
1882   value v2;
1883
1884   while (v != Val_int (0)) {
1885     v2 = Field (v, 0);
1886     flags |= 1 << Int_val (v2);
1887     v = Field (v, 1);
1888   }
1889
1890   return flags;
1891 }
1892
1893 static hive_set_value *
1894 HiveSetValue_val (value v)
1895 {
1896   hive_set_value *val = malloc (sizeof (hive_set_value));
1897
1898   val->key = String_val (Field (v, 0));
1899   val->t = HiveType_val (Field (v, 1));
1900   val->len = caml_string_length (Field (v, 2));
1901   val->value = String_val (Field (v, 2));
1902
1903   return val;
1904 }
1905
1906 static hive_set_value *
1907 HiveSetValues_val (value v)
1908 {
1909   size_t nr_values = Wosize_val (v);
1910   hive_set_value *values = malloc (nr_values * sizeof (hive_set_value));
1911   size_t i;
1912   value v2;
1913
1914   for (i = 0; i < nr_values; ++i) {
1915     v2 = Field (v, i);
1916     values[i].key = String_val (Field (v2, 0));
1917     values[i].t = HiveType_val (Field (v2, 1));
1918     values[i].len = caml_string_length (Field (v2, 2));
1919     values[i].value = String_val (Field (v2, 2));
1920   }
1921
1922   return values;
1923 }
1924
1925 static hive_type
1926 HiveType_val (value v)
1927 {
1928   if (Is_long (v))
1929     return Int_val (v); /* REG_NONE etc. */
1930   else
1931     return Int32_val (Field (v, 0)); /* REG_UNKNOWN of int32 */
1932 }
1933
1934 static value
1935 Val_hive_type (hive_type t)
1936 {
1937   CAMLparam0 ();
1938   CAMLlocal2 (rv, v);
1939
1940   if (t <= %d)
1941     CAMLreturn (Val_int (t));
1942   else {
1943     rv = caml_alloc (1, 0); /* REG_UNKNOWN of int32 */
1944     v = caml_copy_int32 (t);
1945     caml_modify (&Field (rv, 0), v);
1946     CAMLreturn (rv);
1947   }
1948 }
1949
1950 static value
1951 copy_int_array (size_t *xs)
1952 {
1953   CAMLparam0 ();
1954   CAMLlocal2 (v, rv);
1955   size_t nr, i;
1956
1957   for (nr = 0; xs[nr] != 0; ++nr)
1958     ;
1959   if (nr == 0)
1960     CAMLreturn (Atom (0));
1961   else {
1962     rv = caml_alloc (nr, 0);
1963     for (i = 0; i < nr; ++i) {
1964       v = Val_int (xs[i]);
1965       Store_field (rv, i, v); /* Safe because v is not a block. */
1966     }
1967     CAMLreturn (rv);
1968   }
1969 }
1970
1971 static value
1972 copy_type_len (size_t len, hive_type t)
1973 {
1974   CAMLparam0 ();
1975   CAMLlocal2 (v, rv);
1976
1977   rv = caml_alloc (2, 0);
1978   v = Val_hive_type (t);
1979   Store_field (rv, 0, v);
1980   v = Val_int (len);
1981   Store_field (rv, 1, v);
1982   CAMLreturn (rv);
1983 }
1984
1985 static value
1986 copy_type_value (const char *r, size_t len, hive_type t)
1987 {
1988   CAMLparam0 ();
1989   CAMLlocal2 (v, rv);
1990
1991   rv = caml_alloc (2, 0);
1992   v = Val_hive_type (t);
1993   Store_field (rv, 0, v);
1994   v = caml_alloc_string (len);
1995   memcpy (String_val (v), r, len);
1996   caml_modify (&Field (rv, 1), v);
1997   CAMLreturn (rv);
1998 }
1999
2000 /* Raise exceptions. */
2001 static void
2002 raise_error (const char *function)
2003 {
2004   /* Save errno early in case it gets trashed. */
2005   int err = errno;
2006
2007   CAMLparam0 ();
2008   CAMLlocal3 (v1, v2, v3);
2009
2010   v1 = caml_copy_string (function);
2011   v2 = unix_error_of_code (err);
2012   v3 = caml_copy_string (strerror (err));
2013   value vvv[] = { v1, v2, v3 };
2014   caml_raise_with_args (*caml_named_value (\"ocaml_hivex_error\"), 3, vvv);
2015
2016   CAMLnoreturn;
2017 }
2018
2019 static void
2020 raise_closed (const char *function)
2021 {
2022   CAMLparam0 ();
2023   CAMLlocal1 (v);
2024
2025   v = caml_copy_string (function);
2026   caml_raise_with_arg (*caml_named_value (\"ocaml_hivex_closed\"), v);
2027
2028   CAMLnoreturn;
2029 }
2030
2031 /* Allocate handles and deal with finalization. */
2032 static void
2033 hivex_finalize (value hv)
2034 {
2035   hive_h *h = Hiveh_val (hv);
2036   if (h) hivex_close (h);
2037 }
2038
2039 static struct custom_operations hivex_custom_operations = {
2040   (char *) \"hivex_custom_operations\",
2041   hivex_finalize,
2042   custom_compare_default,
2043   custom_hash_default,
2044   custom_serialize_default,
2045   custom_deserialize_default
2046 };
2047
2048 static value
2049 Val_hiveh (hive_h *h)
2050 {
2051   CAMLparam0 ();
2052   CAMLlocal1 (rv);
2053
2054   rv = caml_alloc_custom (&hivex_custom_operations,
2055                           sizeof (hive_h *), 0, 1);
2056   Hiveh_val (rv) = h;
2057
2058   CAMLreturn (rv);
2059 }
2060 " max_hive_type
2061
2062 and generate_perl_pm () =
2063   generate_header HashStyle LGPLv2plus;
2064
2065   pr "\
2066 =pod
2067
2068 =head1 NAME
2069
2070 Win::Hivex - Perl bindings for reading and writing Windows Registry hive files
2071
2072 =head1 SYNOPSIS
2073
2074  use Win::Hivex;
2075
2076  $h = Win::Hivex->open ('SOFTWARE');
2077  $root_node = $h->root ();
2078  print $h->node_name ($root_node);
2079
2080 =head1 DESCRIPTION
2081
2082 The C<Win::Hivex> module provides a Perl XS binding to the
2083 L<hivex(3)> API for reading and writing Windows Registry binary
2084 hive files.
2085
2086 =head1 ERRORS
2087
2088 All errors turn into calls to C<croak> (see L<Carp(3)>).
2089
2090 =head1 METHODS
2091
2092 =over 4
2093
2094 =cut
2095
2096 package Win::Hivex;
2097
2098 use strict;
2099 use warnings;
2100
2101 require XSLoader;
2102 XSLoader::load ('Win::Hivex');
2103
2104 =item open
2105
2106  $h = Win::Hivex->open ($filename,";
2107
2108   List.iter (
2109     fun (_, flag, _) ->
2110       pr "\n                        [%s => 1,]" (String.lowercase flag)
2111   ) open_flags;
2112
2113   pr ")
2114
2115 Open a Windows Registry binary hive file.
2116
2117 The C<verbose> and C<debug> flags enable different levels of
2118 debugging messages.
2119
2120 The C<write> flag is required if you will be modifying the
2121 hive file (see L<hivex(3)/WRITING TO HIVE FILES>).
2122
2123 This function returns a hive handle.  The hive handle is
2124 closed automatically when its reference count drops to 0.
2125
2126 =cut
2127
2128 sub open {
2129   my $proto = shift;
2130   my $class = ref ($proto) || $proto;
2131   my $filename = shift;
2132   my %%flags = @_;
2133   my $flags = 0;
2134
2135 ";
2136
2137   List.iter (
2138     fun (n, flag, description) ->
2139       pr "  # %s\n" description;
2140       pr "  $flags += %d if $flags{%s};\n" n (String.lowercase flag)
2141   ) open_flags;
2142
2143   pr "\
2144
2145   my $self = Win::Hivex::_open ($filename, $flags);
2146   bless $self, $class;
2147   return $self;
2148 }
2149
2150 ";
2151
2152   List.iter (
2153     fun (name, style, _, longdesc) ->
2154       (* The close call isn't explicit in Perl: handles are closed
2155        * when their reference count drops to 0.
2156        *
2157        * The open call is coded specially in Perl.
2158        *
2159        * Therefore we don't generate prototypes for these two calls:
2160        *)
2161       if fst style <> RErrDispose && List.hd (snd style) = AHive then (
2162         let longdesc = replace_str longdesc "C<hivex_" "C<" in
2163         pr "=item %s\n\n " name;
2164         generate_perl_prototype name style;
2165         pr "\n\n";
2166         pr "%s\n\n" longdesc;
2167
2168         (match fst style with
2169          | RErr
2170          | RErrDispose
2171          | RHive
2172          | RString
2173          | RStringList
2174          | RLenType
2175          | RLenTypeVal
2176          | RInt32
2177          | RInt64 -> ()
2178          | RSize ->
2179              pr "\
2180 This returns a size.\n\n"
2181          | RNode ->
2182              pr "\
2183 This returns a node handle.\n\n"
2184          | RNodeNotFound ->
2185              pr "\
2186 This returns a node handle, or C<undef> if the node was not found.\n\n"
2187          | RNodeList ->
2188              pr "\
2189 This returns a list of node handles.\n\n"
2190          | RValue ->
2191              pr "\
2192 This returns a value handle.\n\n"
2193          | RValueList ->
2194              pr "\
2195 This returns a list of value handles.\n\n"
2196         );
2197
2198         if List.mem ASetValues (snd style) then
2199           pr "C<@values> is an array of (keys, value) pairs.
2200 Each element should be a hashref containing C<key>, C<t> (type)
2201 and C<data>.
2202
2203 Any existing values stored at the node are discarded, and their
2204 C<value> handles become invalid.  Thus you can remove all
2205 values stored at C<node> by passing C<@values = []>.\n\n"
2206       )
2207   ) functions;
2208
2209   pr "\
2210 =cut
2211
2212 1;
2213
2214 =back
2215
2216 =head1 COPYRIGHT
2217
2218 Copyright (C) %s Red Hat Inc.
2219
2220 =head1 LICENSE
2221
2222 Please see the file COPYING.LIB for the full license.
2223
2224 =head1 SEE ALSO
2225
2226 L<hivex(3)>,
2227 L<hivexsh(1)>,
2228 L<http://libguestfs.org>,
2229 L<Sys::Guestfs(3)>.
2230
2231 =cut
2232 " copyright_years
2233
2234 and generate_perl_prototype name style =
2235   (* Return type. *)
2236   (match fst style with
2237    | RErr
2238    | RErrDispose -> ()
2239    | RHive -> pr "$h = "
2240    | RSize -> pr "$size = "
2241    | RNode
2242    | RNodeNotFound -> pr "$node = "
2243    | RNodeList -> pr "@nodes = "
2244    | RValue -> pr "$value = "
2245    | RValueList -> pr "@values = "
2246    | RString -> pr "$string = "
2247    | RStringList -> pr "@strings = "
2248    | RLenType -> pr "($type, $len) = "
2249    | RLenTypeVal -> pr "($type, $data) = "
2250    | RInt32 -> pr "$int32 = "
2251    | RInt64 -> pr "$int64 = "
2252   );
2253
2254   let args = List.tl (snd style) in
2255
2256   (* AUnusedFlags is dropped in the bindings. *)
2257   let args = List.filter ((<>) AUnusedFlags) args in
2258
2259   pr "$h->%s (" name;
2260
2261   let comma = ref false in
2262   List.iter (
2263     fun arg ->
2264       if !comma then pr ", "; comma := true;
2265       match arg with
2266       | AHive -> pr "$h"
2267       | ANode n
2268       | AValue n
2269       | AString n -> pr "$%s" n
2270       | AStringNullable n -> pr "[$%s|undef]" n
2271       | AOpenFlags -> pr "[flags]"
2272       | AUnusedFlags -> assert false
2273       | ASetValues -> pr "\\@values"
2274       | ASetValue -> pr "$val"
2275   ) args;
2276
2277   pr ")"
2278
2279 and generate_perl_xs () =
2280   generate_header CStyle LGPLv2plus;
2281
2282   pr "\
2283 #include \"EXTERN.h\"
2284 #include \"perl.h\"
2285 #include \"XSUB.h\"
2286
2287 #include <string.h>
2288 #include <hivex.h>
2289 #include <inttypes.h>
2290
2291 static SV *
2292 my_newSVll(long long val) {
2293 #ifdef USE_64_BIT_ALL
2294   return newSViv(val);
2295 #else
2296   char buf[100];
2297   int len;
2298   len = snprintf(buf, 100, \"%%\" PRId64, val);
2299   return newSVpv(buf, len);
2300 #endif
2301 }
2302
2303 #if 0
2304 static SV *
2305 my_newSVull(unsigned long long val) {
2306 #ifdef USE_64_BIT_ALL
2307   return newSVuv(val);
2308 #else
2309   char buf[100];
2310   int len;
2311   len = snprintf(buf, 100, \"%%\" PRIu64, val);
2312   return newSVpv(buf, len);
2313 #endif
2314 }
2315 #endif
2316
2317 #if 0
2318 /* http://www.perlmonks.org/?node_id=680842 */
2319 static char **
2320 XS_unpack_charPtrPtr (SV *arg) {
2321   char **ret;
2322   AV *av;
2323   I32 i;
2324
2325   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
2326     croak (\"array reference expected\");
2327
2328   av = (AV *)SvRV (arg);
2329   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
2330   if (!ret)
2331     croak (\"malloc failed\");
2332
2333   for (i = 0; i <= av_len (av); i++) {
2334     SV **elem = av_fetch (av, i, 0);
2335
2336     if (!elem || !*elem)
2337       croak (\"missing element in list\");
2338
2339     ret[i] = SvPV_nolen (*elem);
2340   }
2341
2342   ret[i] = NULL;
2343
2344   return ret;
2345 }
2346 #endif
2347
2348 /* Handle set_values parameter. */
2349 typedef struct pl_set_values {
2350   size_t nr_values;
2351   hive_set_value *values;
2352 } pl_set_values;
2353
2354 static pl_set_values
2355 unpack_pl_set_values (SV *sv)
2356 {
2357   pl_set_values ret;
2358   AV *av;
2359   I32 i;
2360
2361   if (!sv || !SvOK (sv) || !SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV)
2362     croak (\"array reference expected\");
2363
2364   av = (AV *)SvRV(sv);
2365   ret.nr_values = av_len (av) + 1;
2366   ret.values = malloc (ret.nr_values * sizeof (hive_set_value));
2367   if (!ret.values)
2368     croak (\"malloc failed\");
2369
2370   for (i = 0; i <= av_len (av); i++) {
2371     SV **hvp = av_fetch (av, i, 0);
2372
2373     if (!hvp || !*hvp || !SvROK (*hvp) || SvTYPE (SvRV (*hvp)) != SVt_PVHV)
2374       croak (\"missing element in list or not a hash ref\");
2375
2376     HV *hv = (HV *)SvRV(*hvp);
2377
2378     SV **svp;
2379     svp = hv_fetch (hv, \"key\", 3, 0);
2380     if (!svp || !*svp)
2381       croak (\"missing 'key' in hash\");
2382     ret.values[i].key = SvPV_nolen (*svp);
2383
2384     svp = hv_fetch (hv, \"t\", 1, 0);
2385     if (!svp || !*svp)
2386       croak (\"missing 't' in hash\");
2387     ret.values[i].t = SvIV (*svp);
2388
2389     svp = hv_fetch (hv, \"value\", 5, 0);
2390     if (!svp || !*svp)
2391       croak (\"missing 'value' in hash\");
2392     ret.values[i].value = SvPV (*svp, ret.values[i].len);
2393   }
2394
2395   return ret;
2396 }
2397
2398 static hive_set_value *
2399 unpack_set_value (SV *sv)
2400 {
2401   hive_set_value *ret;
2402
2403   if (!sv || !SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVHV)
2404     croak (\"not a hash ref\");
2405
2406   ret = malloc (sizeof (hive_set_value));
2407   if (ret == NULL)
2408     croak (\"malloc failed\");
2409
2410   HV *hv = (HV *)SvRV(sv);
2411
2412   SV **svp;
2413   svp = hv_fetch (hv, \"key\", 3, 0);
2414   if (!svp || !*svp)
2415     croak (\"missing 'key' in hash\");
2416   ret->key = SvPV_nolen (*svp);
2417
2418   svp = hv_fetch (hv, \"t\", 1, 0);
2419   if (!svp || !*svp)
2420     croak (\"missing 't' in hash\");
2421   ret->t = SvIV (*svp);
2422
2423   svp = hv_fetch (hv, \"value\", 5, 0);
2424   if (!svp || !*svp)
2425     croak (\"missing 'value' in hash\");
2426   ret->value = SvPV (*svp, ret->len);
2427
2428   return ret;
2429 }
2430
2431 MODULE = Win::Hivex  PACKAGE = Win::Hivex
2432
2433 PROTOTYPES: ENABLE
2434
2435 hive_h *
2436 _open (filename, flags)
2437       char *filename;
2438       int flags;
2439    CODE:
2440       RETVAL = hivex_open (filename, flags);
2441       if (!RETVAL)
2442         croak (\"hivex_open: %%s: %%s\", filename, strerror (errno));
2443  OUTPUT:
2444       RETVAL
2445
2446 void
2447 DESTROY (h)
2448       hive_h *h;
2449  PPCODE:
2450       if (hivex_close (h) == -1)
2451         croak (\"hivex_close: %%s\", strerror (errno));
2452
2453 ";
2454
2455   List.iter (
2456     fun (name, style, _, longdesc) ->
2457       (* The close and open calls are handled specially above. *)
2458       if fst style <> RErrDispose && List.hd (snd style) = AHive then (
2459         (match fst style with
2460          | RErr -> pr "void\n"
2461          | RErrDispose -> failwith "perl bindings cannot handle a call which disposes of the handle"
2462          | RHive -> failwith "perl bindings cannot handle a call which returns a handle"
2463          | RSize
2464          | RNode
2465          | RNodeNotFound
2466          | RValue
2467          | RString -> pr "SV *\n"
2468          | RNodeList
2469          | RValueList
2470          | RStringList
2471          | RLenType
2472          | RLenTypeVal -> pr "void\n"
2473          | RInt32 -> pr "SV *\n"
2474          | RInt64 -> pr "SV *\n"
2475         );
2476
2477         (* Call and arguments. *)
2478         let perl_params =
2479           filter_map (function
2480                       | AUnusedFlags -> None
2481                       | arg -> Some (name_of_argt arg)) (snd style) in
2482
2483         let c_params =
2484           List.map (function
2485                     | AUnusedFlags -> "0"
2486                     | ASetValues -> "values.nr_values, values.values"
2487                     | arg -> name_of_argt arg) (snd style) in
2488
2489         pr "%s (%s)\n" name (String.concat ", " perl_params);
2490         iteri (
2491           fun i ->
2492             function
2493             | AHive ->
2494                 pr "      hive_h *h;\n"
2495             | ANode n
2496             | AValue n ->
2497                 pr "      int %s;\n" n
2498             | AString n ->
2499                 pr "      char *%s;\n" n
2500             | AStringNullable n ->
2501                 (* http://www.perlmonks.org/?node_id=554277 *)
2502                 pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n i i
2503             | AOpenFlags ->
2504                 pr "      int flags;\n"
2505             | AUnusedFlags -> ()
2506             | ASetValues ->
2507                 pr "      pl_set_values values = unpack_pl_set_values (ST(%d));\n" i
2508             | ASetValue ->
2509                 pr "      hive_set_value *val = unpack_set_value (ST(%d));\n" i
2510         ) (snd style);
2511
2512         let free_args () =
2513           List.iter (
2514             function
2515             | ASetValues ->
2516                 pr "      free (values.values);\n"
2517             | ASetValue ->
2518                 pr "      free (val);\n"
2519             | AHive | ANode _ | AValue _ | AString _ | AStringNullable _
2520             | AOpenFlags | AUnusedFlags -> ()
2521           ) (snd style)
2522         in
2523
2524         (* Code. *)
2525         (match fst style with
2526          | RErr ->
2527              pr "PREINIT:\n";
2528              pr "      int r;\n";
2529              pr " PPCODE:\n";
2530              pr "      r = hivex_%s (%s);\n"
2531                name (String.concat ", " c_params);
2532              free_args ();
2533              pr "      if (r == -1)\n";
2534              pr "        croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2535                name;
2536
2537          | RErrDispose -> assert false
2538          | RHive -> assert false
2539
2540          | RSize
2541          | RNode
2542          | RValue ->
2543              pr "PREINIT:\n";
2544              pr "      /* hive_node_h = hive_value_h = size_t so we cheat\n";
2545              pr "         here to simplify the generator */\n";
2546              pr "      size_t r;\n";
2547              pr "   CODE:\n";
2548              pr "      r = hivex_%s (%s);\n"
2549                name (String.concat ", " c_params);
2550              free_args ();
2551              pr "      if (r == 0)\n";
2552              pr "        croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2553                name;
2554              pr "      RETVAL = newSViv (r);\n";
2555              pr " OUTPUT:\n";
2556              pr "      RETVAL\n"
2557
2558          | RNodeNotFound ->
2559              pr "PREINIT:\n";
2560              pr "      hive_node_h r;\n";
2561              pr "   CODE:\n";
2562              pr "      errno = 0;\n";
2563              pr "      r = hivex_%s (%s);\n"
2564                name (String.concat ", " c_params);
2565              free_args ();
2566              pr "      if (r == 0 && errno != 0)\n";
2567              pr "        croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2568                name;
2569              pr "      if (r == 0)\n";
2570              pr "        RETVAL = &PL_sv_undef;\n";
2571              pr "      else\n";
2572              pr "        RETVAL = newSViv (r);\n";
2573              pr " OUTPUT:\n";
2574              pr "      RETVAL\n"
2575
2576          | RString ->
2577              pr "PREINIT:\n";
2578              pr "      char *r;\n";
2579              pr "   CODE:\n";
2580              pr "      r = hivex_%s (%s);\n"
2581                name (String.concat ", " c_params);
2582              free_args ();
2583              pr "      if (r == NULL)\n";
2584              pr "        croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2585                name;
2586              pr "      RETVAL = newSVpv (r, 0);\n";
2587              pr "      free (r);\n";
2588              pr " OUTPUT:\n";
2589              pr "      RETVAL\n"
2590
2591          | RNodeList
2592          | RValueList ->
2593              pr "PREINIT:\n";
2594              pr "      size_t *r;\n";
2595              pr "      int i, n;\n";
2596              pr " PPCODE:\n";
2597              pr "      r = hivex_%s (%s);\n"
2598                name (String.concat ", " c_params);
2599              free_args ();
2600              pr "      if (r == NULL)\n";
2601              pr "        croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2602                name;
2603              pr "      for (n = 0; r[n] != 0; ++n) /**/;\n";
2604              pr "      EXTEND (SP, n);\n";
2605              pr "      for (i = 0; i < n; ++i)\n";
2606              pr "        PUSHs (sv_2mortal (newSViv (r[i])));\n";
2607              pr "      free (r);\n";
2608
2609          | RStringList ->
2610              pr "PREINIT:\n";
2611              pr "      char **r;\n";
2612              pr "      int i, n;\n";
2613              pr " PPCODE:\n";
2614              pr "      r = hivex_%s (%s);\n"
2615                name (String.concat ", " c_params);
2616              free_args ();
2617              pr "      if (r == NULL)\n";
2618              pr "        croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2619                name;
2620              pr "      for (n = 0; r[n] != NULL; ++n) /**/;\n";
2621              pr "      EXTEND (SP, n);\n";
2622              pr "      for (i = 0; i < n; ++i) {\n";
2623              pr "        PUSHs (sv_2mortal (newSVpv (r[i], 0)));\n";
2624              pr "        free (r[i]);\n";
2625              pr "      }\n";
2626              pr "      free (r);\n";
2627
2628          | RLenType ->
2629              pr "PREINIT:\n";
2630              pr "      int r;\n";
2631              pr "      size_t len;\n";
2632              pr "      hive_type type;\n";
2633              pr " PPCODE:\n";
2634              pr "      r = hivex_%s (%s, &type, &len);\n"
2635                name (String.concat ", " c_params);
2636              free_args ();
2637              pr "      if (r == -1)\n";
2638              pr "        croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2639                name;
2640              pr "      EXTEND (SP, 2);\n";
2641              pr "      PUSHs (sv_2mortal (newSViv (type)));\n";
2642              pr "      PUSHs (sv_2mortal (newSViv (len)));\n";
2643
2644          | RLenTypeVal ->
2645              pr "PREINIT:\n";
2646              pr "      char *r;\n";
2647              pr "      size_t len;\n";
2648              pr "      hive_type type;\n";
2649              pr " PPCODE:\n";
2650              pr "      r = hivex_%s (%s, &type, &len);\n"
2651                name (String.concat ", " c_params);
2652              free_args ();
2653              pr "      if (r == NULL)\n";
2654              pr "        croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2655                name;
2656              pr "      EXTEND (SP, 2);\n";
2657              pr "      PUSHs (sv_2mortal (newSViv (type)));\n";
2658              pr "      PUSHs (sv_2mortal (newSVpvn (r, len)));\n";
2659              pr "      free (r);\n";
2660
2661          | RInt32 ->
2662              pr "PREINIT:\n";
2663              pr "      int32_t r;\n";
2664              pr "   CODE:\n";
2665              pr "      errno = 0;\n";
2666              pr "      r = hivex_%s (%s);\n"
2667                name (String.concat ", " c_params);
2668              free_args ();
2669              pr "      if (r == -1 && errno != 0)\n";
2670              pr "        croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2671                name;
2672              pr "      RETVAL = newSViv (r);\n";
2673              pr " OUTPUT:\n";
2674              pr "      RETVAL\n"
2675
2676          | RInt64 ->
2677              pr "PREINIT:\n";
2678              pr "      int64_t r;\n";
2679              pr "   CODE:\n";
2680              pr "      errno = 0;\n";
2681              pr "      r = hivex_%s (%s);\n"
2682                name (String.concat ", " c_params);
2683              free_args ();
2684              pr "      if (r == -1 && errno != 0)\n";
2685              pr "        croak (\"%%s: %%s\", \"%s\", strerror (errno));\n"
2686                name;
2687              pr "      RETVAL = my_newSVll (r);\n";
2688              pr " OUTPUT:\n";
2689              pr "      RETVAL\n"
2690         );
2691         pr "\n"
2692       )
2693   ) functions
2694
2695 and generate_python_c () =
2696   generate_header CStyle LGPLv2plus;
2697
2698   pr "\
2699 #define PY_SSIZE_T_CLEAN 1
2700 #include <Python.h>
2701
2702 #if PY_VERSION_HEX < 0x02050000
2703 typedef int Py_ssize_t;
2704 #define PY_SSIZE_T_MAX INT_MAX
2705 #define PY_SSIZE_T_MIN INT_MIN
2706 #endif
2707
2708 #include <stdio.h>
2709 #include <stdlib.h>
2710 #include <assert.h>
2711
2712 #include \"hivex.h\"
2713
2714 #ifndef HAVE_PYCAPSULE_NEW
2715 typedef struct {
2716   PyObject_HEAD
2717   hive_h *h;
2718 } Pyhivex_Object;
2719 #endif
2720
2721 static hive_h *
2722 get_handle (PyObject *obj)
2723 {
2724   assert (obj);
2725   assert (obj != Py_None);
2726 #ifndef HAVE_PYCAPSULE_NEW
2727   return ((Pyhivex_Object *) obj)->h;
2728 #else
2729   return (hive_h *) PyCapsule_GetPointer(obj, \"hive_h\");
2730 #endif
2731 }
2732
2733 static PyObject *
2734 put_handle (hive_h *h)
2735 {
2736   assert (h);
2737 #ifndef HAVE_PYCAPSULE_NEW
2738   return
2739     PyCObject_FromVoidPtrAndDesc ((void *) h, (char *) \"hive_h\", NULL);
2740 #else
2741   return PyCapsule_New ((void *) h, \"hive_h\", NULL);
2742 #endif
2743 }
2744
2745 /* This returns pointers into the Python objects, which should
2746  * not be freed.
2747  */
2748 static int
2749 get_value (PyObject *v, hive_set_value *ret)
2750 {
2751   PyObject *obj;
2752
2753   obj = PyDict_GetItemString (v, \"key\");
2754   if (!obj) {
2755     PyErr_SetString (PyExc_RuntimeError, \"no 'key' element in dictionary\");
2756     return -1;
2757   }
2758   if (!PyString_Check (obj)) {
2759     PyErr_SetString (PyExc_RuntimeError, \"'key' element is not a string\");
2760     return -1;
2761   }
2762   ret->key = PyString_AsString (obj);
2763
2764   obj = PyDict_GetItemString (v, \"t\");
2765   if (!obj) {
2766     PyErr_SetString (PyExc_RuntimeError, \"no 't' element in dictionary\");
2767     return -1;
2768   }
2769   if (!PyInt_Check (obj)) {
2770     PyErr_SetString (PyExc_RuntimeError, \"'t' element is not an integer\");
2771     return -1;
2772   }
2773   ret->t = PyInt_AsLong (obj);
2774
2775   obj = PyDict_GetItemString (v, \"value\");
2776   if (!obj) {
2777     PyErr_SetString (PyExc_RuntimeError, \"no 'value' element in dictionary\");
2778     return -1;
2779   }
2780   if (!PyString_Check (obj)) {
2781     PyErr_SetString (PyExc_RuntimeError, \"'value' element is not a string\");
2782     return -1;
2783   }
2784   ret->value = PyString_AsString (obj);
2785   ret->len = PyString_Size (obj);
2786
2787   return 0;
2788 }
2789
2790 typedef struct py_set_values {
2791   size_t nr_values;
2792   hive_set_value *values;
2793 } py_set_values;
2794
2795 static int
2796 get_values (PyObject *v, py_set_values *ret)
2797 {
2798   Py_ssize_t slen;
2799   size_t len, i;
2800
2801   if (!PyList_Check (v)) {
2802     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
2803     return -1;
2804   }
2805
2806   slen = PyList_Size (v);
2807   if (slen < 0) {
2808     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
2809     return -1;
2810   }
2811   len = (size_t) slen;
2812   ret->nr_values = len;
2813   ret->values = malloc (len * sizeof (hive_set_value));
2814   if (!ret->values) {
2815     PyErr_SetString (PyExc_RuntimeError, strerror (errno));
2816     return -1;
2817   }
2818
2819   for (i = 0; i < len; ++i) {
2820     if (get_value (PyList_GetItem (v, i), &(ret->values[i])) == -1) {
2821       free (ret->values);
2822       return -1;
2823     }
2824   }
2825
2826   return 0;
2827 }
2828
2829 static PyObject *
2830 put_string_list (char * const * const argv)
2831 {
2832   PyObject *list;
2833   size_t argc, i;
2834
2835   for (argc = 0; argv[argc] != NULL; ++argc)
2836     ;
2837
2838   list = PyList_New (argc);
2839   for (i = 0; i < argc; ++i)
2840     PyList_SetItem (list, i, PyString_FromString (argv[i]));
2841
2842   return list;
2843 }
2844
2845 static void
2846 free_strings (char **argv)
2847 {
2848   size_t argc;
2849
2850   for (argc = 0; argv[argc] != NULL; ++argc)
2851     free (argv[argc]);
2852   free (argv);
2853 }
2854
2855 /* Since hive_node_t is the same as hive_value_t this also works for values. */
2856 static PyObject *
2857 put_node_list (hive_node_h *nodes)
2858 {
2859   PyObject *list;
2860   size_t argc, i;
2861
2862   for (argc = 0; nodes[argc] != 0; ++argc)
2863     ;
2864
2865   list = PyList_New (argc);
2866   for (i = 0; i < argc; ++i)
2867     PyList_SetItem (list, i, PyLong_FromLongLong ((long) nodes[i]));
2868
2869   return list;
2870 }
2871
2872 static PyObject *
2873 put_len_type (size_t len, hive_type t)
2874 {
2875   PyObject *r = PyTuple_New (2);
2876   PyTuple_SetItem (r, 0, PyInt_FromLong ((long) t));
2877   PyTuple_SetItem (r, 1, PyLong_FromLongLong ((long) len));
2878   return r;
2879 }
2880
2881 static PyObject *
2882 put_val_type (char *val, size_t len, hive_type t)
2883 {
2884   PyObject *r = PyTuple_New (2);
2885   PyTuple_SetItem (r, 0, PyInt_FromLong ((long) t));
2886   PyTuple_SetItem (r, 1, PyString_FromStringAndSize (val, len));
2887   return r;
2888 }
2889
2890 ";
2891
2892   (* Generate functions. *)
2893   List.iter (
2894     fun (name, style, _, longdesc) ->
2895       pr "static PyObject *\n";
2896       pr "py_hivex_%s (PyObject *self, PyObject *args)\n" name;
2897       pr "{\n";
2898       pr "  PyObject *py_r;\n";
2899
2900       let error_code =
2901         match fst style with
2902         | RErr -> pr "  int r;\n"; "-1"
2903         | RErrDispose -> pr "  int r;\n"; "-1"
2904         | RHive -> pr "  hive_h *r;\n"; "NULL"
2905         | RSize -> pr "  size_t r;\n"; "0"
2906         | RNode -> pr "  hive_node_h r;\n"; "0"
2907         | RNodeNotFound ->
2908             pr "  errno = 0;\n";
2909             pr "  hive_node_h r;\n";
2910             "0 && errno != 0"
2911         | RNodeList -> pr "  hive_node_h *r;\n"; "NULL"
2912         | RValue -> pr "  hive_value_h r;\n"; "0"
2913         | RValueList -> pr "  hive_value_h *r;\n"; "NULL"
2914         | RString -> pr "  char *r;\n"; "NULL"
2915         | RStringList -> pr "  char **r;\n"; "NULL"
2916         | RLenType ->
2917             pr "  int r;\n";
2918             pr "  size_t len;\n";
2919             pr "  hive_type t;\n";
2920             "-1"
2921         | RLenTypeVal ->
2922             pr "  char *r;\n";
2923             pr "  size_t len;\n";
2924             pr "  hive_type t;\n";
2925             "NULL"
2926         | RInt32 ->
2927             pr "  errno = 0;\n";
2928             pr "  int32_t r;\n";
2929             "-1 && errno != 0"
2930         | RInt64 ->
2931             pr "  errno = 0;\n";
2932             pr "  int64_t r;\n";
2933             "-1 && errno != 0" in
2934
2935       (* Call and arguments. *)
2936       let c_params =
2937         List.map (function
2938                   | AUnusedFlags -> "0"
2939                   | ASetValues -> "values.nr_values, values.values"
2940                   | ASetValue -> "&val"
2941                   | arg -> name_of_argt arg) (snd style) in
2942       let c_params =
2943         match fst style with
2944         | RLenType | RLenTypeVal -> c_params @ ["&t"; "&len"]
2945         | _ -> c_params in
2946
2947       List.iter (
2948         function
2949         | AHive ->
2950             pr "  hive_h *h;\n";
2951             pr "  PyObject *py_h;\n"
2952         | ANode n
2953         | AValue n ->
2954             pr "  long %s;\n" n
2955         | AString n
2956         | AStringNullable n ->
2957             pr "  char *%s;\n" n
2958         | AOpenFlags ->
2959             pr "  int flags;\n"
2960         | AUnusedFlags -> ()
2961         | ASetValues ->
2962             pr "  py_set_values values;\n";
2963             pr "  PyObject *py_values;\n"
2964         | ASetValue ->
2965             pr "  hive_set_value val;\n";
2966             pr "  PyObject *py_val;\n"
2967       ) (snd style);
2968
2969       pr "\n";
2970
2971       (* Convert the required parameters. *)
2972       pr "  if (!PyArg_ParseTuple (args, (char *) \"";
2973       List.iter (
2974         function
2975         | AHive ->
2976             pr "O"
2977         | ANode n
2978         | AValue n ->
2979             pr "l"
2980         | AString n ->
2981             pr "s"
2982         | AStringNullable n ->
2983             pr "z"
2984         | AOpenFlags ->
2985             pr "i"
2986         | AUnusedFlags -> ()
2987         | ASetValues
2988         | ASetValue ->
2989             pr "O"
2990       ) (snd style);
2991
2992       pr ":hivex_%s\"" name;
2993
2994       List.iter (
2995         function
2996         | AHive ->
2997             pr ", &py_h"
2998         | ANode n
2999         | AValue n ->
3000             pr ", &%s" n
3001         | AString n
3002         | AStringNullable n ->
3003             pr ", &%s" n
3004         | AOpenFlags ->
3005             pr ", &flags"
3006         | AUnusedFlags -> ()
3007         | ASetValues ->
3008             pr ", &py_values"
3009         | ASetValue ->
3010             pr ", &py_val"
3011         ) (snd style);
3012
3013       pr "))\n";
3014       pr "    return NULL;\n";
3015
3016       (* Convert some Python argument types to C. *)
3017       List.iter (
3018         function
3019         | AHive ->
3020             pr "  h = get_handle (py_h);\n"
3021         | ANode _
3022         | AValue _
3023         | AString _
3024         | AStringNullable _
3025         | AOpenFlags
3026         | AUnusedFlags -> ()
3027         | ASetValues ->
3028             pr "  if (get_values (py_values, &values) == -1)\n";
3029             pr "    return NULL;\n"
3030         | ASetValue ->
3031             pr "  if (get_value (py_val, &val) == -1)\n";
3032             pr "    return NULL;\n"
3033       ) (snd style);
3034
3035       (* Call the C function. *)
3036       pr "  r = hivex_%s (%s);\n" name (String.concat ", " c_params);
3037
3038       (* Free up arguments. *)
3039       List.iter (
3040         function
3041         | AHive | ANode _ | AValue _
3042         | AString _ | AStringNullable _
3043         | AOpenFlags | AUnusedFlags -> ()
3044         | ASetValues ->
3045             pr "  free (values.values);\n"
3046         | ASetValue -> ()
3047       ) (snd style);
3048
3049       (* Check for errors from C library. *)
3050       pr "  if (r == %s) {\n" error_code;
3051       pr "    PyErr_SetString (PyExc_RuntimeError,\n";
3052       pr "                     strerror (errno));\n";
3053       pr "    return NULL;\n";
3054       pr "  }\n";
3055       pr "\n";
3056
3057       (* Convert return value to Python. *)
3058       (match fst style with
3059        | RErr
3060        | RErrDispose ->
3061            pr "  Py_INCREF (Py_None);\n";
3062            pr "  py_r = Py_None;\n"
3063        | RHive ->
3064            pr "  py_r = put_handle (r);\n"
3065        | RSize
3066        | RNode ->
3067            pr "  py_r = PyLong_FromLongLong (r);\n"
3068        | RNodeNotFound ->
3069            pr "  if (r)\n";
3070            pr "    py_r = PyLong_FromLongLong (r);\n";
3071            pr "  else {\n";
3072            pr "    Py_INCREF (Py_None);\n";
3073            pr "    py_r = Py_None;\n";
3074            pr "  }\n";
3075        | RNodeList
3076        | RValueList ->
3077            pr "  py_r = put_node_list (r);\n";
3078            pr "  free (r);\n"
3079        | RValue ->
3080            pr "  py_r = PyLong_FromLongLong (r);\n"
3081        | RString ->
3082            pr "  py_r = PyString_FromString (r);\n";
3083            pr "  free (r);"
3084        | RStringList ->
3085            pr "  py_r = put_string_list (r);\n";
3086            pr "  free_strings (r);\n"
3087        | RLenType ->
3088            pr "  py_r = put_len_type (len, t);\n"
3089        | RLenTypeVal ->
3090            pr "  py_r = put_val_type (r, len, t);\n";
3091            pr "  free (r);\n"
3092        | RInt32 ->
3093            pr "  py_r = PyInt_FromLong ((long) r);\n"
3094        | RInt64 ->
3095            pr "  py_r = PyLong_FromLongLong (r);\n"
3096       );
3097       pr "  return py_r;\n";
3098       pr "}\n";
3099       pr "\n"
3100   ) functions;
3101
3102   (* Table of functions. *)
3103   pr "static PyMethodDef methods[] = {\n";
3104   List.iter (
3105     fun (name, _, _, _) ->
3106       pr "  { (char *) \"%s\", py_hivex_%s, METH_VARARGS, NULL },\n"
3107         name name
3108   ) functions;
3109   pr "  { NULL, NULL, 0, NULL }\n";
3110   pr "};\n";
3111   pr "\n";
3112
3113   (* Init function. *)
3114   pr "\
3115 void
3116 initlibhivexmod (void)
3117 {
3118   static int initialized = 0;
3119
3120   if (initialized) return;
3121   Py_InitModule ((char *) \"libhivexmod\", methods);
3122   initialized = 1;
3123 }
3124 "
3125
3126 and generate_python_py () =
3127   generate_header HashStyle LGPLv2plus;
3128
3129   pr "\
3130 u\"\"\"Python bindings for hivex
3131
3132 import hivex
3133 h = hivex.Hivex (filename)
3134
3135 The hivex module provides Python bindings to the hivex API for
3136 examining and modifying Windows Registry 'hive' files.
3137
3138 Read the hivex(3) man page to find out how to use the API.
3139 \"\"\"
3140
3141 import libhivexmod
3142
3143 class Hivex:
3144     \"\"\"Instances of this class are hivex API handles.\"\"\"
3145
3146     def __init__ (self, filename";
3147
3148   List.iter (
3149     fun (_, flag, _) -> pr ", %s = False" (String.lowercase flag)
3150   ) open_flags;
3151
3152   pr "):
3153         \"\"\"Create a new hivex handle.\"\"\"
3154         flags = 0
3155 ";
3156
3157   List.iter (
3158     fun (n, flag, description) ->
3159       pr "        # %s\n" description;
3160       pr "        if %s: flags += %d\n" (String.lowercase flag) n
3161   ) open_flags;
3162
3163   pr "        self._o = libhivexmod.open (filename, flags)
3164
3165     def __del__ (self):
3166         libhivexmod.close (self._o)
3167
3168 ";
3169
3170   List.iter (
3171     fun (name, style, shortdesc, _) ->
3172       (* The close and open calls are handled specially above. *)
3173       if fst style <> RErrDispose && List.hd (snd style) = AHive then (
3174         let args = List.tl (snd style) in
3175         let args = List.filter (
3176           function AOpenFlags | AUnusedFlags -> false
3177           | _ -> true
3178         ) args in
3179
3180         pr "    def %s (self" name;
3181         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
3182         pr "):\n";
3183         pr "        u\"\"\"%s\"\"\"\n" shortdesc;
3184         pr "        return libhivexmod.%s (self._o" name;
3185         List.iter (
3186           fun arg ->
3187             pr ", ";
3188             match arg with
3189             | AHive -> assert false
3190             | ANode n | AValue n
3191             | AString n | AStringNullable n -> pr "%s" n
3192             | AOpenFlags
3193             | AUnusedFlags -> assert false
3194             | ASetValues -> pr "values"
3195             | ASetValue -> pr "val"
3196         ) args;
3197         pr ")\n";
3198         pr "\n"
3199       )
3200   ) functions
3201
3202 and generate_ruby_c () =
3203   generate_header CStyle LGPLv2plus;
3204
3205   pr "\
3206 #include <stdio.h>
3207 #include <stdlib.h>
3208 #include <stdint.h>
3209
3210 #include <ruby.h>
3211
3212 #include \"hivex.h\"
3213
3214 #include \"extconf.h\"
3215
3216 /* For Ruby < 1.9 */
3217 #ifndef RARRAY_LEN
3218 #define RARRAY_LEN(r) (RARRAY((r))->len)
3219 #endif
3220
3221 static VALUE m_hivex;                   /* hivex module */
3222 static VALUE c_hivex;                   /* hive_h handle */
3223 static VALUE e_Error;                   /* used for all errors */
3224
3225 static void
3226 ruby_hivex_free (void *hvp)
3227 {
3228   hive_h *h = hvp;
3229
3230   if (h)
3231     hivex_close (h);
3232 }
3233
3234 static void
3235 get_value (VALUE valv, hive_set_value *val)
3236 {
3237   VALUE key = rb_hash_lookup (valv, ID2SYM (rb_intern (\"key\")));
3238   VALUE type = rb_hash_lookup (valv, ID2SYM (rb_intern (\"type\")));
3239   VALUE value = rb_hash_lookup (valv, ID2SYM (rb_intern (\"value\")));
3240
3241   val->key = StringValueCStr (key);
3242   val->t = NUM2ULL (type);
3243   val->len = RSTRING (value)->len;
3244   val->value = RSTRING (value)->ptr;
3245 }
3246
3247 static hive_set_value *
3248 get_values (VALUE valuesv, size_t *nr_values)
3249 {
3250   size_t i;
3251   hive_set_value *ret;
3252
3253   *nr_values = RARRAY_LEN (valuesv);
3254   ret = malloc (sizeof (*ret) * *nr_values);
3255   if (ret == NULL)
3256     abort ();
3257
3258   for (i = 0; i < *nr_values; ++i) {
3259     VALUE v = rb_ary_entry (valuesv, i);
3260     get_value (v, &ret[i]);
3261   }
3262
3263   return ret;
3264 }
3265
3266 ";
3267
3268   List.iter (
3269     fun (name, (ret, args), shortdesc, longdesc) ->
3270       let () =
3271         (* Generate rdoc. *)
3272         let doc = replace_str longdesc "C<hivex_" "C<h." in
3273         let doc = pod2text ~width:60 name doc in
3274         let doc = String.concat "\n * " doc in
3275         let doc = trim doc in
3276
3277         let call, args =
3278           match args with
3279           | AHive :: args -> "h." ^ name, args
3280           | args -> "Hivex::" ^ name, args in
3281         let args = filter_map (
3282           function
3283           | AUnusedFlags -> None
3284           | args -> Some (name_of_argt args)
3285         ) args in
3286         let args = String.concat ", " args in
3287
3288         let ret =
3289           match ret with
3290           | RErr | RErrDispose -> "nil"
3291           | RHive -> "Hivex::Hivex"
3292           | RSize | RNode | RNodeNotFound -> "integer"
3293           | RNodeList -> "list"
3294           | RValue -> "integer"
3295           | RValueList -> "list"
3296           | RString -> "string"
3297           | RStringList -> "list"
3298           | RLenType -> "hash"
3299           | RLenTypeVal -> "hash"
3300           | RInt32 -> "integer"
3301           | RInt64 -> "integer" in
3302
3303         pr "\
3304 /*
3305  * call-seq:
3306  *   %s(%s) -> %s
3307  *
3308  * %s
3309  *
3310  * %s
3311  *
3312  * (For the C API documentation for this function, see
3313  * +hivex_%s+[http://libguestfs.org/hivex.3.html#hivex_%s]).
3314  */
3315 " call args ret shortdesc doc name name in
3316
3317       (* Generate the function. *)
3318       pr "static VALUE\n";
3319       pr "ruby_hivex_%s (" name;
3320
3321       let () =
3322         (* If the first argument is not AHive, then this is a module-level
3323          * function, and Ruby passes an implicit module argument which we
3324          * must ignore.  Otherwise the first argument is the hive handle.
3325          *)
3326         let args =
3327           match args with
3328           | AHive :: args -> pr "VALUE hv"; args
3329           | args -> pr "VALUE modulev"; args in
3330         List.iter (
3331           function
3332           | AUnusedFlags -> ()
3333           | arg ->
3334             pr ", VALUE %sv" (name_of_argt arg)
3335         ) args;
3336         pr ")\n" in
3337
3338       pr "{\n";
3339
3340       List.iter (
3341         function
3342         | AHive ->
3343           pr "  hive_h *h;\n";
3344           pr "  Data_Get_Struct (hv, hive_h, h);\n";
3345           pr "  if (!h)\n";
3346           pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\",\n";
3347           pr "              \"%s\");\n" name;
3348         | ANode n ->
3349           pr "  hive_node_h %s = NUM2ULL (%sv);\n" n n
3350         | AValue n ->
3351           pr "  hive_value_h %s = NUM2ULL (%sv);\n" n n
3352         | AString n ->
3353           pr "  const char *%s = StringValueCStr (%sv);\n" n n;
3354         | AStringNullable n ->
3355           pr "  const char *%s =\n" n;
3356           pr "    !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n
3357         | AOpenFlags ->
3358           pr "  int flags = 0;\n";
3359           List.iter (
3360             fun (n, flag, _) ->
3361               pr "  if (RTEST (rb_hash_lookup (flagsv, ID2SYM (rb_intern (\"%s\")))))\n"
3362                 (String.lowercase flag);
3363               pr "    flags += %d;\n" n
3364           ) open_flags
3365         | AUnusedFlags -> ()
3366         | ASetValues ->
3367           pr "  size_t nr_values;\n";
3368           pr "  hive_set_value *values;\n";
3369           pr "  values = get_values (valuesv, &nr_values);\n"
3370         | ASetValue ->
3371           pr "  hive_set_value val;\n";
3372           pr "  get_value (valv, &val);\n"
3373       ) args;
3374       pr "\n";
3375
3376       let error_code =
3377         match ret with
3378         | RErr -> pr "  int r;\n"; "-1"
3379         | RErrDispose -> pr "  int r;\n"; "-1"
3380         | RHive -> pr "  hive_h *r;\n"; "NULL"
3381         | RSize -> pr "  size_t r;\n"; "0"
3382         | RNode -> pr "  hive_node_h r;\n"; "0"
3383         | RNodeNotFound ->
3384             pr "  errno = 0;\n";
3385             pr "  hive_node_h r;\n";
3386             "0 && errno != 0"
3387         | RNodeList -> pr "  hive_node_h *r;\n"; "NULL"
3388         | RValue -> pr "  hive_value_h r;\n"; "0"
3389         | RValueList -> pr "  hive_value_h *r;\n"; "NULL"
3390         | RString -> pr "  char *r;\n"; "NULL"
3391         | RStringList -> pr "  char **r;\n"; "NULL"
3392         | RLenType ->
3393             pr "  int r;\n";
3394             pr "  size_t len;\n";
3395             pr "  hive_type t;\n";
3396             "-1"
3397         | RLenTypeVal ->
3398             pr "  char *r;\n";
3399             pr "  size_t len;\n";
3400             pr "  hive_type t;\n";
3401             "NULL"
3402         | RInt32 ->
3403             pr "  errno = 0;\n";
3404             pr "  int32_t r;\n";
3405             "-1 && errno != 0"
3406         | RInt64 ->
3407             pr "  errno = 0;\n";
3408             pr "  int64_t r;\n";
3409             "-1 && errno != 0" in
3410       pr "\n";
3411
3412       let c_params =
3413         List.map (function
3414                   | ASetValues -> ["nr_values"; "values"]
3415                   | ASetValue -> ["&val"]
3416                   | AUnusedFlags -> ["0"]
3417                   | arg -> [name_of_argt arg]) args in
3418       let c_params =
3419         match ret with
3420         | RLenType | RLenTypeVal -> c_params @ [["&t"; "&len"]]
3421         | _ -> c_params in
3422       let c_params = List.concat c_params in
3423
3424       pr "  r = hivex_%s (%s" name (List.hd c_params);
3425       List.iter (pr ", %s") (List.tl c_params);
3426       pr ");\n";
3427       pr "\n";
3428
3429       (* Dispose of the hive handle (even if hivex_close returns error). *)
3430       (match ret with
3431        | RErrDispose ->
3432            pr "  /* So we don't double-free in the finalizer. */\n";
3433            pr "  DATA_PTR (hv) = NULL;\n";
3434            pr "\n";
3435        | _ -> ()
3436       );
3437
3438       List.iter (
3439         function
3440         | AHive
3441         | ANode _
3442         | AValue _
3443         | AString _
3444         | AStringNullable _
3445         | AOpenFlags
3446         | AUnusedFlags -> ()
3447         | ASetValues ->
3448           pr "  free (values);\n"
3449         | ASetValue -> ()
3450       ) args;
3451
3452       (* Check for errors from C library. *)
3453       pr "  if (r == %s)\n" error_code;
3454       pr "    rb_raise (e_Error, \"%%s\", strerror (errno));\n";
3455       pr "\n";
3456
3457       (match ret with
3458       | RErr | RErrDispose ->
3459         pr "  return Qnil;\n"
3460       | RHive ->
3461         pr "  return Data_Wrap_Struct (c_hivex, NULL, ruby_hivex_free, r);\n"
3462       | RSize
3463       | RNode
3464       | RValue
3465       | RInt64 ->
3466         pr "  return ULL2NUM (r);\n"
3467       | RInt32 ->
3468         pr "  return INT2NUM (r);\n"
3469       | RNodeNotFound ->
3470         pr "  if (r)\n";
3471         pr "    return ULL2NUM (r);\n";
3472         pr "  else\n";
3473         pr "    return Qnil;\n"
3474       | RNodeList
3475       | RValueList ->
3476         pr "  size_t i, len = 0;\n";
3477         pr "  for (i = 0; r[i] != 0; ++i) len++;\n";
3478         pr "  VALUE rv = rb_ary_new2 (len);\n";
3479         pr "  for (i = 0; r[i] != 0; ++i)\n";
3480         pr "    rb_ary_push (rv, ULL2NUM (r[i]));\n";
3481         pr "  free (r);\n";
3482         pr "  return rv;\n"
3483       | RString ->
3484         pr "  VALUE rv = rb_str_new2 (r);\n";
3485         pr "  free (r);\n";
3486         pr "  return rv;\n"
3487       | RStringList ->
3488         pr "  size_t i, len = 0;\n";
3489         pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
3490         pr "  VALUE rv = rb_ary_new2 (len);\n";
3491         pr "  for (i = 0; r[i] != NULL; ++i) {\n";
3492         pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
3493         pr "    free (r[i]);\n";
3494         pr "  }\n";
3495         pr "  free (r);\n";
3496         pr "  return rv;\n"
3497       | RLenType ->
3498         pr "  VALUE rv = rb_hash_new ();\n";
3499         pr "  rb_hash_aset (rv, ID2SYM (rb_intern (\"len\")), INT2NUM (len));\n";
3500         pr "  rb_hash_aset (rv, ID2SYM (rb_intern (\"type\")), INT2NUM (t));\n";
3501         pr "  return rv;\n"
3502       | RLenTypeVal ->
3503         pr "  VALUE rv = rb_hash_new ();\n";
3504         pr "  rb_hash_aset (rv, ID2SYM (rb_intern (\"len\")), INT2NUM (len));\n";
3505         pr "  rb_hash_aset (rv, ID2SYM (rb_intern (\"type\")), INT2NUM (t));\n";
3506         pr "  rb_hash_aset (rv, ID2SYM (rb_intern (\"value\")), rb_str_new (r, len));\n";
3507         pr "  free (r);\n";
3508         pr "  return rv;\n"
3509       );
3510
3511       pr "}\n";
3512       pr "\n"
3513   ) functions;
3514
3515   pr "\
3516 /* Initialize the module. */
3517 void Init__hivex ()
3518 {
3519   m_hivex = rb_define_module (\"Hivex\");
3520   c_hivex = rb_define_class_under (m_hivex, \"Hivex\", rb_cObject);
3521   e_Error = rb_define_class_under (m_hivex, \"Error\", rb_eStandardError);
3522
3523   /* XXX How to pass arguments? */
3524 #if 0
3525 #ifdef HAVE_RB_DEFINE_ALLOC_FUNC
3526   rb_define_alloc_func (c_hivex, ruby_hivex_open);
3527 #endif
3528 #endif
3529
3530 ";
3531
3532   (* Methods. *)
3533   List.iter (
3534     fun (name, (_, args), _, _) ->
3535       let args = List.filter (
3536         function
3537         | AUnusedFlags -> false
3538         | _ -> true
3539       ) args in
3540       let nr_args = List.length args in
3541       match args with
3542       | AHive :: _ ->
3543         pr "  rb_define_method (c_hivex, \"%s\",\n" name;
3544         pr "                    ruby_hivex_%s, %d);\n" name (nr_args-1)
3545       | args -> (* class function *)
3546         pr "  rb_define_module_function (m_hivex, \"%s\",\n" name;
3547         pr "                             ruby_hivex_%s, %d);\n" name nr_args
3548   ) functions;
3549
3550   pr "}\n"
3551
3552 let output_to filename k =
3553   let filename_new = filename ^ ".new" in
3554   chan := open_out filename_new;
3555   k ();
3556   close_out !chan;
3557   chan := Pervasives.stdout;
3558
3559   (* Is the new file different from the current file? *)
3560   if Sys.file_exists filename && files_equal filename filename_new then
3561     unlink filename_new                 (* same, so skip it *)
3562   else (
3563     (* different, overwrite old one *)
3564     (try chmod filename 0o644 with Unix_error _ -> ());
3565     rename filename_new filename;
3566     chmod filename 0o444;
3567     printf "written %s\n%!" filename;
3568   )
3569
3570 let perror msg = function
3571   | Unix_error (err, _, _) ->
3572       eprintf "%s: %s\n" msg (error_message err)
3573   | exn ->
3574       eprintf "%s: %s\n" msg (Printexc.to_string exn)
3575
3576 (* Main program. *)
3577 let () =
3578   let lock_fd =
3579     try openfile "configure.ac" [O_RDWR] 0
3580     with
3581     | Unix_error (ENOENT, _, _) ->
3582         eprintf "\
3583 You are probably running this from the wrong directory.
3584 Run it from the top source directory using the command
3585   generator/generator.ml
3586 ";
3587         exit 1
3588     | exn ->
3589         perror "open: configure.ac" exn;
3590         exit 1 in
3591
3592   (* Acquire a lock so parallel builds won't try to run the generator
3593    * twice at the same time.  Subsequent builds will wait for the first
3594    * one to finish.  Note the lock is released implicitly when the
3595    * program exits.
3596    *)
3597   (try lockf lock_fd F_LOCK 1
3598    with exn ->
3599      perror "lock: configure.ac" exn;
3600      exit 1);
3601
3602   check_functions ();
3603
3604   output_to "lib/hivex.h" generate_c_header;
3605   output_to "lib/hivex.pod" generate_c_pod;
3606
3607   output_to "lib/hivex.syms" generate_linker_script;
3608
3609   output_to "ocaml/hivex.mli" generate_ocaml_interface;
3610   output_to "ocaml/hivex.ml" generate_ocaml_implementation;
3611   output_to "ocaml/hivex_c.c" generate_ocaml_c;
3612
3613   output_to "perl/lib/Win/Hivex.pm" generate_perl_pm;
3614   output_to "perl/Hivex.xs" generate_perl_xs;
3615
3616   output_to "python/hivex.py" generate_python_py;
3617   output_to "python/hivex-py.c" generate_python_c;
3618
3619   output_to "ruby/ext/hivex/_hivex.c" generate_ruby_c;
3620
3621   (* Always generate this file last, and unconditionally.  It's used
3622    * by the Makefile to know when we must re-run the generator.
3623    *)
3624   let chan = open_out "generator/stamp-generator" in
3625   fprintf chan "1\n";
3626   close_out chan;
3627
3628   printf "generated %d lines of code\n" !lines