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