Index: trunk/include/regfi.h
===================================================================
--- trunk/include/regfi.h	(revision 160)
+++ trunk/include/regfi.h	(revision 161)
@@ -60,4 +60,14 @@
 #define REGFI_MSG_WARN  0x0004
 #define REGFI_MSG_ERROR 0x0010
+
+typedef uint8 REGFI_ENCODING;
+/* regfi library supported character encodings */
+#define REGFI_ENCODING_ASCII   0
+#define REGFI_ENCODING_UTF8    1
+#define REGFI_ENCODING_DEFAULT REGFI_ENCODING_ASCII
+/* UTF16LE is not supported for output */
+#define REGFI_ENCODING_UTF16LE 2
+
+#define REGFI_NUM_ENCODINGS    3
 
 /* Windows is lame */
@@ -360,5 +370,5 @@
   
   /* header information */
-  uint16 key_type;
+  uint16 flags;
   uint8  magic[REGFI_CELL_MAGIC_SIZE];
   NTTIME mtime;
@@ -479,5 +489,5 @@
   void_stack* key_positions;
   REGFI_NK_REC* cur_key;
-  const char* string_encoding;
+  REGFI_ENCODING string_encoding;
   uint32 cur_subkey;
   uint32 cur_value;
@@ -529,11 +539,11 @@
  *   file            -- The opened registry file the iterator should be
  *                      created for.
- *   output_encoding -- An integer representing the output string encoding.
- *                      These integers currently map to a specific set of 
- *                      iconv(3) encodings.
+ *   output_encoding -- Character encoding that strings should be returned in.
+ *                      Only supply the REGFI_ENCODING_* constants, as others 
+ *                      will be rejected.
  *                      The following values are currently accepted:
- *                      0 - default (currently US-ASCII//TRANSLIT)
- *                      1 - US-ASCII//TRANSLIT
- *                      2 - UTF-8//TRANSLIT
+ *                      REGFI_ENCODING_DEFAULT (currently REGFI_ENCODING_ASCII)
+ *                      REGFI_ENCODING_ASCII
+ *                      REGFI_ENCODING_UTF8
  *
  *                      XXX: This encoding only applies to specific data 
@@ -545,5 +555,5 @@
  */
 REGFI_ITERATOR*       regfi_iterator_new(REGFI_FILE* file,
-					 uint32 output_encoding);
+					 REGFI_ENCODING output_encoding);
 void                  regfi_iterator_free(REGFI_ITERATOR* i);
 bool                  regfi_iterator_down(REGFI_ITERATOR* i);
@@ -578,4 +588,5 @@
 /********************************************************/
 REGFI_NK_REC*         regfi_load_key(REGFI_FILE* file, uint32 offset, 
+				     REGFI_ENCODING output_encoding, 
 				     bool strict);
 REGFI_VK_REC*         regfi_load_value(REGFI_FILE* file, uint32 offset, 
@@ -597,5 +608,5 @@
 					  bool strict);
 bool                  regfi_interpret_data(REGFI_FILE* file, 
-					   const char* string_encoding,
+					   REGFI_ENCODING string_encoding,
 					   uint32 type, REGFI_DATA* data);
 void                  regfi_free_classname(REGFI_CLASSNAME* classname);
@@ -666,5 +677,6 @@
 /*    Private Functions             */
 /************************************/
-REGFI_NK_REC*         regfi_rootkey(REGFI_FILE* file);
+REGFI_NK_REC*         regfi_rootkey(REGFI_FILE* file, 
+				    REGFI_ENCODING output_encoding);
 void                  regfi_subkeylist_free(REGFI_SUBKEY_LIST* list);
 uint32                regfi_read(int fd, uint8* buf, uint32* length);
@@ -689,5 +701,6 @@
 REGFI_VK_REC*         regfi_copy_vk(const REGFI_VK_REC* vk);
 int32                 regfi_calc_maxsize(REGFI_FILE* file, uint32 offset);
-int32                 regfi_conv_charset(const char* output_charset, 
+int32                 regfi_conv_charset(const char* input_charset, 
+					 const char* output_charset,
 					 uint8* input, char* output, 
 					 uint32 input_len, uint32 output_max);
Index: trunk/lib/regfi.c
===================================================================
--- trunk/lib/regfi.c	(revision 160)
+++ trunk/lib/regfi.c	(revision 161)
@@ -19,5 +19,5 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Id$
@@ -33,4 +33,6 @@
    "MULTI_SZ", "RSRC_LIST", "RSRC_DESC", "RSRC_REQ_LIST", "QWORD"};
 
+const char* regfi_encoding_names[] =
+  {"US-ASCII//TRANSLIT", "UTF-8//TRANSLIT", "UTF-16LE//TRANSLIT"};
 
 
@@ -102,5 +104,19 @@
 
 
-/* Returns NULL on error */
+/******************************************************************************
+ * Returns NULL for an invalid e
+ *****************************************************************************/
+static const char* regfi_encoding_int2str(REGFI_ENCODING e)
+{
+  if(e < REGFI_NUM_ENCODINGS)
+    return regfi_encoding_names[e];
+
+  return NULL;
+}
+
+
+/******************************************************************************
+ * Returns NULL for an invalid val
+ *****************************************************************************/
 const char* regfi_type_val2str(unsigned int val)
 {
@@ -115,5 +131,7 @@
 
 
-/* Returns -1 on error */
+/******************************************************************************
+ * Returns -1 on error
+ *****************************************************************************/
 int regfi_type_str2val(const char* str)
 {
@@ -1004,9 +1022,11 @@
  *
  ******************************************************************************/
-REGFI_NK_REC* regfi_load_key(REGFI_FILE* file, uint32 offset, bool strict)
+REGFI_NK_REC* regfi_load_key(REGFI_FILE* file, uint32 offset, 
+			     REGFI_ENCODING output_encoding, bool strict)
 {
   REGFI_NK_REC* nk;
   uint32 off;
-  int32 max_size;
+  int32 max_size, tmp_size;
+  REGFI_ENCODING from_encoding;
 
   max_size = regfi_calc_maxsize(file, offset);
@@ -1021,4 +1041,38 @@
     return NULL;
   }
+
+  from_encoding = (nk->flags & REGFI_NK_FLAG_ASCIINAME) 
+    ? REGFI_ENCODING_ASCII : REGFI_ENCODING_UTF16LE;
+
+  if(from_encoding == output_encoding)
+  {
+    nk->keyname_raw = talloc_realloc(nk, nk->keyname_raw, uint8, nk->name_length+1);
+    nk->keyname_raw[nk->name_length] = '\0';
+    nk->keyname = (char*)nk->keyname_raw;
+  }
+  else
+  {
+    nk->keyname = talloc_array(nk, char, nk->name_length+1);
+    if(nk->keyname == NULL)
+    {
+      regfi_free_key(nk);
+      return NULL;
+    }
+
+    tmp_size = regfi_conv_charset(regfi_encoding_int2str(from_encoding),
+				  regfi_encoding_int2str(output_encoding),
+				  nk->keyname_raw, nk->keyname,
+				  nk->name_length, nk->name_length+1);
+    if(tmp_size < 0)
+    {
+      regfi_add_message(file, REGFI_MSG_WARN, "Error occurred while converting"
+			" keyname to encoding %s.  Error message: %s",
+			regfi_encoding_int2str(output_encoding), 
+			strerror(-tmp_size));
+      talloc_free(nk->keyname);
+      nk->keyname = NULL;
+    }
+  }
+
 
   /* get value list */
@@ -1132,5 +1186,6 @@
 /******************************************************************************
  ******************************************************************************/
-REGFI_NK_REC* regfi_find_root_nk(REGFI_FILE* file, const REGFI_HBIN* hbin)
+REGFI_NK_REC* regfi_find_root_nk(REGFI_FILE* file, const REGFI_HBIN* hbin, 
+				 REGFI_ENCODING output_encoding)
 {
   REGFI_NK_REC* nk = NULL;
@@ -1151,8 +1206,8 @@
     if(!unalloc)
     {
-      nk = regfi_load_key(file, cur_offset, true);
+      nk = regfi_load_key(file, cur_offset, output_encoding, true);
       if(nk != NULL)
       {
-	if(nk->key_type & REGFI_NK_FLAG_ROOT)
+	if(nk->flags & REGFI_NK_FLAG_ROOT)
 	  return nk;
       }
@@ -1270,5 +1325,5 @@
  * rest of the file if that fails.
  ******************************************************************************/
-REGFI_NK_REC* regfi_rootkey(REGFI_FILE *file)
+REGFI_NK_REC* regfi_rootkey(REGFI_FILE* file, REGFI_ENCODING output_encoding)
 {
   REGFI_NK_REC* nk = NULL;
@@ -1280,8 +1335,8 @@
 
   root_offset = file->root_cell+REGFI_REGF_SIZE;
-  nk = regfi_load_key(file, root_offset, true);
+  nk = regfi_load_key(file, root_offset, output_encoding, true);
   if(nk != NULL)
   {
-    if(nk->key_type & REGFI_NK_FLAG_ROOT)
+    if(nk->flags & REGFI_NK_FLAG_ROOT)
       return nk;
   }
@@ -1298,5 +1353,5 @@
   {
     hbin = (REGFI_HBIN*)range_list_get(file->hbins, i)->data;
-    nk = regfi_find_root_nk(file, hbin);
+    nk = regfi_find_root_nk(file, hbin, output_encoding);
   }
 
@@ -1335,12 +1390,23 @@
 /******************************************************************************
  *****************************************************************************/
-REGFI_ITERATOR* regfi_iterator_new(REGFI_FILE* file, uint32 output_encoding)
+REGFI_ITERATOR* regfi_iterator_new(REGFI_FILE* file, 
+				   REGFI_ENCODING output_encoding)
 {
   REGFI_NK_REC* root;
-  REGFI_ITERATOR* ret_val = talloc(NULL, REGFI_ITERATOR);
+  REGFI_ITERATOR* ret_val;
+
+  if(output_encoding != REGFI_ENCODING_UTF8
+     && output_encoding != REGFI_ENCODING_ASCII)
+  { 
+    regfi_add_message(file, REGFI_MSG_ERROR, "Invalid output_encoding supplied"
+		      " in creation of regfi iterator.");
+    return NULL;
+  }
+
+  ret_val = talloc(NULL, REGFI_ITERATOR);
   if(ret_val == NULL)
     return NULL;
 
-  root = regfi_rootkey(file);
+  root = regfi_rootkey(file, output_encoding);
   if(root == NULL)
   {
@@ -1361,19 +1427,6 @@
   ret_val->cur_subkey = 0;
   ret_val->cur_value = 0;
-  
-  switch (output_encoding)
-  {
-  case 0:
-  case 1:
-    ret_val->string_encoding = "US-ASCII//TRANSLIT";
-    break;
-  case 2:
-    ret_val->string_encoding = "UTF-8//TRANSLIT";
-    break;
-  default:
-    talloc_free(ret_val);
-    return NULL;
-  }
-  
+  ret_val->string_encoding = output_encoding;
+    
   return ret_val;
 }
@@ -1559,5 +1612,6 @@
   nk_offset = i->cur_key->subkeys->elements[i->cur_subkey].offset;
 
-  return regfi_load_key(i->f, nk_offset+REGFI_REGF_SIZE, true);
+  return regfi_load_key(i->f, nk_offset+REGFI_REGF_SIZE, i->string_encoding, 
+			true);
 }
 
@@ -1695,5 +1749,6 @@
   interpreted = talloc_array(NULL, char, parse_length);
 
-  conv_size = regfi_conv_charset(i->string_encoding, 
+  conv_size = regfi_conv_charset(regfi_encoding_int2str(REGFI_ENCODING_UTF16LE),
+				 regfi_encoding_int2str(i->string_encoding),
 				 raw, interpreted,
 				 parse_length, parse_length);
@@ -1802,5 +1857,5 @@
 /******************************************************************************
  *****************************************************************************/
-bool regfi_interpret_data(REGFI_FILE* file, const char* string_encoding,
+bool regfi_interpret_data(REGFI_FILE* file, REGFI_ENCODING string_encoding,
 			  uint32 type, REGFI_DATA* data)
 {
@@ -1827,5 +1882,6 @@
     }
       
-    tmp_size = regfi_conv_charset(string_encoding, 
+    tmp_size = regfi_conv_charset(regfi_encoding_int2str(REGFI_ENCODING_UTF16LE),
+				  regfi_encoding_int2str(string_encoding),
 				  data->raw, (char*)tmp_str, 
 				  data->size, data->size);
@@ -1893,5 +1949,6 @@
      * then parse and quote fields individually.
      */
-    tmp_size = regfi_conv_charset(string_encoding, 
+    tmp_size = regfi_conv_charset(regfi_encoding_int2str(REGFI_ENCODING_UTF16LE),
+				  regfi_encoding_int2str(string_encoding),
 				  data->raw, (char*)tmp_str,
 				  data->size, data->size);
@@ -1969,10 +2026,9 @@
 
 
-
 /*******************************************************************
  * Convert from UTF-16LE to specified character set. 
  * On error, returns a negative errno code.
  *******************************************************************/
-int32 regfi_conv_charset(const char* output_charset, 
+int32 regfi_conv_charset(const char* input_charset, const char* output_charset,
 			 uint8* input, char* output, 
 			 uint32 input_len, uint32 output_max)
@@ -1985,6 +2041,11 @@
   int ret;
 
+  /* XXX: Consider creating a couple of conversion descriptors earlier,
+   *      storing them on an iterator so they don't have to be recreated
+   *      each time.
+   */
+
   /* Set up conversion descriptor. */
-  conv_desc = iconv_open(output_charset, "UTF-16LE");
+  conv_desc = iconv_open(output_charset, input_charset);
 
   ret = iconv(conv_desc, &inbuf, &in_len, &outbuf, &out_len);
@@ -2227,11 +2288,11 @@
   ret_val->magic[0] = nk_header[0x0];
   ret_val->magic[1] = nk_header[0x1];
-  ret_val->key_type = SVAL(nk_header, 0x2);
-  
-  if((ret_val->key_type & ~REGFI_NK_KNOWN_FLAGS) != 0)
+  ret_val->flags = SVAL(nk_header, 0x2);
+  
+  if((ret_val->flags & ~REGFI_NK_KNOWN_FLAGS) != 0)
   {
     regfi_add_message(file, REGFI_MSG_WARN, "Unknown key flags (0x%.4X) while"
 		      " parsing NK record at offset 0x%.8X.", 
-		      (ret_val->key_type & ~REGFI_NK_KNOWN_FLAGS), offset);
+		      (ret_val->flags & ~REGFI_NK_KNOWN_FLAGS), offset);
   }
 
@@ -2268,4 +2329,5 @@
   ret_val->name_length = SVAL(nk_header, 0x48);
   ret_val->classname_length = SVAL(nk_header, 0x4A);
+  ret_val->keyname = NULL;
 
   if(ret_val->name_length + REGFI_NK_MIN_LENGTH > ret_val->cell_size)
@@ -2293,6 +2355,6 @@
   }
 
-  ret_val->keyname = talloc_array(ret_val, char, ret_val->name_length+1);
-  if(ret_val->keyname == NULL)
+  ret_val->keyname_raw = talloc_array(ret_val, uint8, ret_val->name_length);
+  if(ret_val->keyname_raw == NULL)
   {
     talloc_free(ret_val);
@@ -2302,5 +2364,5 @@
   /* Don't need to seek, should be at the right offset */
   length = ret_val->name_length;
-  if((regfi_read(file->fd, (uint8*)ret_val->keyname, &length) != 0)
+  if((regfi_read(file->fd, (uint8*)ret_val->keyname_raw, &length) != 0)
      || length != ret_val->name_length)
   {
@@ -2310,5 +2372,4 @@
     return NULL;
   }
-  ret_val->keyname[ret_val->name_length] = '\0';
 
   return ret_val;
Index: trunk/src/reglookup-recover.c
===================================================================
--- trunk/src/reglookup-recover.c	(revision 160)
+++ trunk/src/reglookup-recover.c	(revision 161)
@@ -127,5 +127,5 @@
   /* XXX: Add command line option to choose output encoding */
   if(vk->data != NULL 
-     && !regfi_interpret_data(f, "US-ASCII//TRANSLIT", vk->type, vk->data))
+     && !regfi_interpret_data(f, REGFI_ENCODING_ASCII, vk->type, vk->data))
   {
     fprintf(stderr, "WARN: Error occurred while interpreting data for VK record"
@@ -271,5 +271,5 @@
       else
       {
-	if(cur_ancestor->key_type & REGFI_NK_FLAG_ROOT)
+	if(cur_ancestor->flags & REGFI_NK_FLAG_ROOT)
 	  virt_offset = REGFI_OFFSET_NONE;
 	else
Index: trunk/src/reglookup.c
===================================================================
--- trunk/src/reglookup.c	(revision 160)
+++ trunk/src/reglookup.c	(revision 161)
@@ -191,4 +191,5 @@
 {
   const REGFI_ITER_POSITION* cur;
+  const REGFI_NK_REC* tmp_key;
   uint32 buf_left = 127;
   uint32 buf_len = buf_left+1;
@@ -198,5 +199,4 @@
   char* new_buf;
   char* name;
-  const char* cur_name;
   void_stack_iterator* iter;
   
@@ -226,11 +226,16 @@
     cur = void_stack_iterator_next(iter);
     if (cur == NULL)
-      cur_name = i->cur_key->keyname;
-    else
-      cur_name = cur->nk->keyname;
+      tmp_key = i->cur_key;
+    else
+      tmp_key = cur->nk;
+
+    if(tmp_key->keyname == NULL)
+      name = quote_buffer(i->cur_key->keyname_raw, i->cur_key->name_length,
+			  key_special_chars);
+    else
+      name = quote_string(tmp_key->keyname, key_special_chars);
 
     buf[buf_len-buf_left-1] = '/';
     buf_left -= 1;
-    name = quote_string(cur_name, key_special_chars);
     name_len = strlen(name);
     if(name_len+1 > buf_left)
@@ -617,5 +622,5 @@
 
   /* XXX: add command line option to choose output encoding */
-  iter = regfi_iterator_new(f, 0);
+  iter = regfi_iterator_new(f, REGFI_ENCODING_ASCII);
   if(iter == NULL)
   {
