1 /* hivexml - Convert Windows Registry "hive" to XML file.
2 * Copyright (C) 2009 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #include <libxml/xmlwriter.h>
41 #define _(str) dgettext(PACKAGE, (str))
42 //#define N_(str) dgettext(PACKAGE, (str))
48 static char *filetime_to_8601 (int64_t windows_ticks);
50 /* Callback functions. */
51 static int node_start (hive_h *, void *, hive_node_h, const char *name);
52 static int node_end (hive_h *, void *, hive_node_h, const char *name);
53 static int value_string (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *str);
54 static int value_multiple_strings (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, char **argv);
55 static int value_string_invalid_utf16 (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *str);
56 static int value_dword (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, int32_t);
57 static int value_qword (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, int64_t);
58 static int value_binary (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *value);
59 static int value_none (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *value);
60 static int value_other (hive_h *, void *, hive_node_h, hive_value_h, hive_type t, size_t len, const char *key, const char *value);
62 static struct hivex_visitor visitor = {
63 .node_start = node_start,
65 .value_string = value_string,
66 .value_multiple_strings = value_multiple_strings,
67 .value_string_invalid_utf16 = value_string_invalid_utf16,
68 .value_dword = value_dword,
69 .value_qword = value_qword,
70 .value_binary = value_binary,
71 .value_none = value_none,
72 .value_other = value_other
75 #define XML_CHECK(proc, args) \
77 if ((proc args) == -1) { \
78 fprintf (stderr, _("%s: failed to write XML document\n"), #proc); \
79 exit (EXIT_FAILURE); \
84 main (int argc, char *argv[])
86 setlocale (LC_ALL, "");
87 #ifdef HAVE_BINDTEXTDOMAIN
88 bindtextdomain (PACKAGE, LOCALEBASEDIR);
96 while ((c = getopt (argc, argv, "dk")) != EOF) {
99 open_flags |= HIVEX_OPEN_DEBUG;
102 visit_flags |= HIVEX_VISIT_SKIP_BAD;
105 fprintf (stderr, "hivexml [-dk] regfile > output.xml\n");
110 if (optind + 1 != argc) {
111 fprintf (stderr, _("hivexml: missing name of input file\n"));
115 hive_h *h = hivex_open (argv[optind], open_flags);
117 perror (argv[optind]);
121 /* Note both this macro, and xmlTextWriterStartDocument leak memory. There
122 * doesn't seem to be any way to recover that memory, but it's not a
127 xmlTextWriterPtr writer;
128 writer = xmlNewTextWriterFilename ("/dev/stdout", 0);
129 if (writer == NULL) {
130 fprintf (stderr, _("xmlNewTextWriterFilename: failed to create XML writer\n"));
134 XML_CHECK (xmlTextWriterStartDocument, (writer, NULL, "utf-8", NULL));
135 XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "hive"));
137 int64_t hive_mtime = hivex_last_modified (h);
138 if (hive_mtime >= 0) {
139 char *timebuf = filetime_to_8601 (hive_mtime);
141 XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "mtime"));
142 XML_CHECK (xmlTextWriterWriteString, (writer, BAD_CAST timebuf));
143 XML_CHECK (xmlTextWriterEndElement, (writer));
148 if (hivex_visit (h, &visitor, sizeof visitor, writer, visit_flags) == -1) {
149 perror (argv[optind]);
153 if (hivex_close (h) == -1) {
154 perror (argv[optind]);
158 XML_CHECK (xmlTextWriterEndElement, (writer));
159 XML_CHECK (xmlTextWriterEndDocument, (writer));
160 xmlFreeTextWriter (writer);
165 /* Convert Windows filetime to ISO 8601 format.
166 * http://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux/6161842#6161842
168 * Source for time_t->char* conversion: Fiwalk version 0.6.14's
171 * The caller should free the returned buffer.
173 * This function returns NULL on a 0 input. In the context of
174 * hives, which only have mtimes, 0 will always be a complete
178 #define WINDOWS_TICK 10000000LL
179 #define SEC_TO_UNIX_EPOCH 11644473600LL
180 #define TIMESTAMP_BUF_LEN 32
183 filetime_to_8601 (int64_t windows_ticks)
189 if (windows_ticks == 0LL)
192 t = windows_ticks / WINDOWS_TICK - SEC_TO_UNIX_EPOCH;
197 ret = malloc (TIMESTAMP_BUF_LEN);
203 if (strftime (ret, TIMESTAMP_BUF_LEN, "%FT%TZ", tm) == 0) {
212 node_start (hive_h *h, void *writer_v, hive_node_h node, const char *name)
214 int64_t last_modified;
218 xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
219 XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "node"));
220 XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "name", BAD_CAST name));
222 if (node == hivex_root (h)) {
223 XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "root", BAD_CAST "1"));
226 last_modified = hivex_node_timestamp (h, node);
227 if (last_modified >= 0) {
228 timebuf = filetime_to_8601 (last_modified);
230 XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "mtime"));
231 XML_CHECK (xmlTextWriterWriteString, (writer, BAD_CAST timebuf));
232 XML_CHECK (xmlTextWriterEndElement, (writer));
241 node_end (hive_h *h, void *writer_v, hive_node_h node, const char *name)
243 xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
244 XML_CHECK (xmlTextWriterEndElement, (writer));
249 start_value (xmlTextWriterPtr writer,
250 const char *key, const char *type, const char *encoding)
252 XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "value"));
253 XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "type", BAD_CAST type));
255 XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "encoding", BAD_CAST encoding));
257 XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "key", BAD_CAST key));
258 else /* default key */
259 XML_CHECK (xmlTextWriterWriteAttribute, (writer, BAD_CAST "default", BAD_CAST "1"));
263 end_value (xmlTextWriterPtr writer)
265 XML_CHECK (xmlTextWriterEndElement, (writer));
269 value_string (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value,
270 hive_type t, size_t len, const char *key, const char *str)
272 xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
276 case hive_t_string: type = "string"; break;
277 case hive_t_expand_string: type = "expand"; break;
278 case hive_t_link: type = "link"; break;
283 case hive_t_dword_be:
284 case hive_t_multiple_strings:
285 case hive_t_resource_list:
286 case hive_t_full_resource_description:
287 case hive_t_resource_requirements_list:
289 abort (); /* internal error - should not happen */
295 start_value (writer, key, type, NULL);
296 XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value"));
297 XML_CHECK (xmlTextWriterWriteString, (writer, BAD_CAST str));
298 XML_CHECK (xmlTextWriterEndAttribute, (writer));
304 value_multiple_strings (hive_h *h, void *writer_v, hive_node_h node,
305 hive_value_h value, hive_type t, size_t len,
306 const char *key, char **argv)
308 xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
309 start_value (writer, key, "string-list", NULL);
312 for (i = 0; argv[i] != NULL; ++i) {
313 XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "string"));
314 XML_CHECK (xmlTextWriterWriteString, (writer, BAD_CAST argv[i]));
315 XML_CHECK (xmlTextWriterEndElement, (writer));
323 value_string_invalid_utf16 (hive_h *h, void *writer_v, hive_node_h node,
324 hive_value_h value, hive_type t, size_t len,
326 const char *str /* original data */)
328 xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
332 case hive_t_string: type = "bad-string"; break;
333 case hive_t_expand_string: type = "bad-expand"; break;
334 case hive_t_link: type = "bad-link"; break;
335 case hive_t_multiple_strings: type = "bad-string-list"; break;
340 case hive_t_dword_be:
341 case hive_t_resource_list:
342 case hive_t_full_resource_description:
343 case hive_t_resource_requirements_list:
345 abort (); /* internal error - should not happen */
351 start_value (writer, key, type, "base64");
352 XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value"));
353 XML_CHECK (xmlTextWriterWriteBase64, (writer, str, 0, len));
354 XML_CHECK (xmlTextWriterEndAttribute, (writer));
361 value_dword (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value,
362 hive_type t, size_t len, const char *key, int32_t v)
364 xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
365 start_value (writer, key, "int32", NULL);
366 XML_CHECK (xmlTextWriterWriteFormatAttribute, (writer, BAD_CAST "value", "%" PRIi32, v));
372 value_qword (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value,
373 hive_type t, size_t len, const char *key, int64_t v)
375 xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
376 start_value (writer, key, "int64", NULL);
377 XML_CHECK (xmlTextWriterWriteFormatAttribute, (writer, BAD_CAST "value", "%" PRIi64, v));
383 value_binary (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value,
384 hive_type t, size_t len, const char *key, const char *v)
386 xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
387 start_value (writer, key, "binary", "base64");
388 XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value"));
389 XML_CHECK (xmlTextWriterWriteBase64, (writer, v, 0, len));
390 XML_CHECK (xmlTextWriterEndAttribute, (writer));
396 value_none (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value,
397 hive_type t, size_t len, const char *key, const char *v)
399 xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
400 start_value (writer, key, "none", "base64");
402 XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value"));
403 XML_CHECK (xmlTextWriterWriteBase64, (writer, v, 0, len));
404 XML_CHECK (xmlTextWriterEndAttribute, (writer));
411 value_other (hive_h *h, void *writer_v, hive_node_h node, hive_value_h value,
412 hive_type t, size_t len, const char *key, const char *v)
414 xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
421 case hive_t_dword_be:
424 case hive_t_expand_string:
426 case hive_t_multiple_strings:
427 abort (); /* internal error - should not happen */
429 case hive_t_resource_list: type = "resource-list"; break;
430 case hive_t_full_resource_description: type = "resource-description"; break;
431 case hive_t_resource_requirements_list: type = "resource-requirements"; break;
437 start_value (writer, key, type, "base64");
439 XML_CHECK (xmlTextWriterStartAttribute, (writer, BAD_CAST "value"));
440 XML_CHECK (xmlTextWriterWriteBase64, (writer, v, 0, len));
441 XML_CHECK (xmlTextWriterEndAttribute, (writer));