Index: trunk/src/common.c
===================================================================
--- trunk/src/common.c	(revision 158)
+++ trunk/src/common.c	(revision 159)
@@ -160,5 +160,4 @@
   int ret;
 
-  /* Set up conversion descriptor. */
   conv_desc = iconv_open("US-ASCII//TRANSLIT", "UTF-16LE");
 
@@ -229,154 +228,149 @@
  * value, and a non-NULL (*error_msg).
  */
-/* XXX: Part of this function's logic should be pushed into the regfi API.
- *      The structures should be parsed and stored with VK records and only 
- *      escaped/encoded later in reglookup and reglookup-recover.
- */
-static char* data_to_ascii(unsigned char* datap, uint32 len, uint32 type, 
-			   char** error_msg)
-{
-  char* asciip;
-  char* ascii;
-  char* ascii_tmp;
+static char* data_to_ascii(REGFI_DATA* data, char** error_msg)
+{
+  char* ret_val;
   char* cur_quoted;
-  char* tmp_err = NULL;
-  const char* delim;
-  uint32 i;
-  uint32 cur_str_len;
-  uint32 ascii_max;
-  uint32 str_rem, alen;
-  int ret_err;
-
-  if(datap == NULL)
-  {
-    *error_msg = (char*)malloc(24);
-    if(*error_msg == NULL)
-      return NULL;
-    strcpy(*error_msg, "Data pointer was NULL.");
+  char* tmp_ptr;
+  char* delim;
+  uint32 ret_val_left, i, tmp_len;
+
+  if(data == NULL || data->size == 0)
+  {
+    *error_msg = (char*)malloc(37);
+    if(*error_msg == NULL)
+      return NULL;
+    strcpy(*error_msg, "Data pointer was NULL or size was 0.");
     return NULL;
   }
   *error_msg = NULL;
 
-  switch (type) 
+
+  if(data->interpreted_size == 0)
+  {
+    *error_msg = (char*)malloc(51);
+    if(*error_msg == NULL)
+      return NULL;
+    strcpy(*error_msg, "Data could not be interpreted, quoting raw buffer.");
+    return quote_buffer(data->raw, data->size, common_special_chars);
+  }
+
+  switch (data->type) 
   {
   case REG_SZ:
+    ret_val = quote_string((char*)data->interpreted.string, common_special_chars);
+    if(ret_val == NULL && (*error_msg = (char*)malloc(49)) != NULL)
+	strcpy(*error_msg, "Buffer could not be quoted due to unknown error.");
+
+    return ret_val;
+    break;
+
+    
   case REG_EXPAND_SZ:
-    /* REG_LINK is a symbolic link, stored as a unicode string. */
+    ret_val = quote_string((char*)data->interpreted.expand_string, 
+			   common_special_chars);
+    if(ret_val == NULL && (*error_msg = (char*)malloc(49)) != NULL)
+	strcpy(*error_msg, "Buffer could not be quoted due to unknown error.");
+
+    return ret_val;
+    break;
+
   case REG_LINK:
-    /* Sometimes values have binary stored in them.  If the unicode
-     * conversion fails, just quote it raw.
+    ret_val = quote_string((char*)data->interpreted.link, common_special_chars);
+    if(ret_val == NULL && (*error_msg = (char*)malloc(49)) != NULL)
+	strcpy(*error_msg, "Buffer could not be quoted due to unknown error.");
+
+    return ret_val;
+    break;
+
+  case REG_DWORD:
+    ret_val = malloc(sizeof(char)*(8+2+1));
+    if(ret_val == NULL)
+      return NULL;
+
+    sprintf(ret_val, "0x%.8X", data->interpreted.dword);
+    return ret_val;
+    break;
+
+  case REG_DWORD_BE:
+    ret_val = malloc(sizeof(char)*(8+2+1));
+    if(ret_val == NULL)
+      return NULL;
+
+    sprintf(ret_val, "0x%.8X", data->interpreted.dword_be);
+    return ret_val;
+    break;
+
+  case REG_QWORD:
+    ret_val = malloc(sizeof(char)*(16+2+1));
+    if(ret_val == NULL)
+      return NULL;
+
+    sprintf(ret_val, "0x%.16llX", 
+	    (long long unsigned int)data->interpreted.qword);
+    return ret_val;
+    break;
+
+  case REG_MULTI_SZ:
+    ret_val_left = data->interpreted_size*4+1;
+    ret_val = malloc(ret_val_left);
+    if(ret_val == NULL)
+      return NULL;
+
+    tmp_ptr = ret_val;
+    tmp_ptr[0] = '\0';
+    delim = "";
+    for(i=0; data->interpreted.multiple_string[i] != NULL; i++)
+    {
+      cur_quoted = quote_string((char*)data->interpreted.multiple_string[i],
+				subfield_special_chars);
+      if(cur_quoted != NULL && cur_quoted[0] != '\0')
+      {
+	tmp_len = snprintf(tmp_ptr, ret_val_left, "%s%s",delim, cur_quoted);
+	tmp_ptr += tmp_len;
+	ret_val_left -= tmp_len;
+	free(cur_quoted);
+      }
+      delim = "|";
+    }
+
+    return ret_val;
+    break;
+
+    
+  case REG_NONE:
+    return quote_buffer(data->interpreted.none, data->interpreted_size,
+			common_special_chars);
+
+    break;
+
+  case REG_RESOURCE_LIST:
+    return quote_buffer(data->interpreted.resource_list, data->interpreted_size,
+			common_special_chars);
+
+    break;
+
+  case REG_FULL_RESOURCE_DESCRIPTOR:
+    return quote_buffer(data->interpreted.full_resource_descriptor, 
+			data->interpreted_size, common_special_chars);
+
+    break;
+
+  case REG_RESOURCE_REQUIREMENTS_LIST:
+    return quote_buffer(data->interpreted.resource_requirements_list,
+			data->interpreted_size, common_special_chars);
+
+    break;
+
+  case REG_BINARY:
+    return quote_buffer(data->interpreted.binary, data->interpreted_size,
+			common_special_chars);
+
+    break;
+
+  default:
+    /* This shouldn't happen, since the regfi routines won't interpret 
+     * unknown types, but just as a safety measure against library changes... 
      */
-    cur_quoted = quote_unicode(datap, len, common_special_chars, &tmp_err);
-    if(cur_quoted == NULL)
-    {
-      if(tmp_err == NULL && (*error_msg = (char*)malloc(49)) != NULL)
-	strcpy(*error_msg, "Buffer could not be quoted due to unknown error.");
-      else if((*error_msg = (char*)malloc(42+strlen(tmp_err))) != NULL)
-      {
-	sprintf(*error_msg, "Buffer could not be quoted due to error: %s", 
-		tmp_err);
-	free(tmp_err);
-      }
-    }
-    else if (tmp_err != NULL)
-      *error_msg = tmp_err;
-    return cur_quoted;
-    break;
-
-  case REG_DWORD:
-    ascii_max = sizeof(char)*(8+2+1);
-    ascii = malloc(ascii_max);
-    if(ascii == NULL)
-      return NULL;
-
-    snprintf(ascii, ascii_max, "0x%.2X%.2X%.2X%.2X", 
-	     datap[3], datap[2], datap[1], datap[0]);
-    return ascii;
-    break;
-
-  case REG_DWORD_BE:
-    ascii_max = sizeof(char)*(8+2+1);
-    ascii = malloc(ascii_max);
-    if(ascii == NULL)
-      return NULL;
-
-    snprintf(ascii, ascii_max, "0x%.2X%.2X%.2X%.2X", 
-	     datap[0], datap[1], datap[2], datap[3]);
-    return ascii;
-    break;
-
-  case REG_QWORD:
-    ascii_max = sizeof(char)*(16+2+1);
-    ascii = malloc(ascii_max);
-    if(ascii == NULL)
-      return NULL;
-
-    snprintf(ascii, ascii_max, "0x%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X",
-	     datap[7], datap[6], datap[5], datap[4],
-	     datap[3], datap[2], datap[1], datap[0]);
-    return ascii;
-    break;
-    
-  case REG_MULTI_SZ:
-    ascii_max = sizeof(char)*(len*4+1);
-    ascii_tmp = malloc(ascii_max);
-    if(ascii_tmp == NULL)
-      return NULL;
-
-    /* Attempt to convert entire string from UTF-16LE to ASCII, 
-     * then parse and quote fields individually.
-     * If this fails, simply quote entire buffer as binary. 
-     */
-    ret_err = uni_to_ascii(datap, ascii_tmp, len, ascii_max);
-    if(ret_err < 0)
-    {
-      tmp_err = strerror(-ret_err);
-      *error_msg = (char*)malloc(61+strlen(tmp_err));
-      if(*error_msg == NULL)
-      {
-	free(ascii_tmp);
-	return NULL;
-      }
-
-      sprintf(*error_msg, "MULTI_SZ unicode conversion"
-	      " failed with '%s'. Quoting as binary.", tmp_err);
-      ascii = quote_buffer(datap, len, subfield_special_chars);
-    }
-    else
-    {
-      ascii = malloc(ascii_max);
-      if(ascii == NULL)
-      {
-	free(ascii_tmp);
-	return NULL;
-      }
-      asciip = ascii;
-      asciip[0] = '\0';
-      str_rem = ascii_max;
-      delim = "";
-      for(i=0; i<ret_err; i+=cur_str_len+1)
-      {
-	cur_str_len = strlen(ascii_tmp+i);
-	if(ascii_tmp[i] != '\0')
-	{
-	  cur_quoted = quote_string(ascii_tmp+i, subfield_special_chars);
-	  if(cur_quoted != NULL)
-	  {
-	    alen = snprintf(asciip, str_rem, "%s%s", delim, cur_quoted);
-	    asciip += alen;
-	    str_rem -= alen;
-	    free(cur_quoted);
-	  }
-	}
-	delim = "|";
-      }
-    }
-
-    free(ascii_tmp);
-    return ascii;
-    break;
-
-  /* XXX: Dont know what to do with these yet, just print as binary... */
-  default:
     *error_msg = (char*)malloc(65);
     if(*error_msg == NULL)
@@ -384,16 +378,8 @@
     sprintf(*error_msg,
 	    "Unrecognized registry data type (0x%.8X); quoting as binary.",
-	    type);
+	    data->type);
+    return quote_buffer(data->raw, data->size, common_special_chars);
+  }
     
-  case REG_NONE:
-  case REG_RESOURCE_LIST:
-  case REG_FULL_RESOURCE_DESCRIPTOR:
-  case REG_RESOURCE_REQUIREMENTS_LIST:
-
-  case REG_BINARY:
-    return quote_buffer(datap, len, common_special_chars);
-    break;
-  }
-
   return NULL;
 }
Index: trunk/src/reglookup-recover.c
===================================================================
--- trunk/src/reglookup-recover.c	(revision 158)
+++ trunk/src/reglookup-recover.c	(revision 159)
@@ -111,24 +111,5 @@
   char* conv_error = NULL;
   const char* str_type = NULL;
-  uint32 size = vk->data_size;
-
-  /* Microsoft's documentation indicates that "available memory" is 
-   * the limit on value sizes.  Annoying.  We limit it to 1M which 
-   * should rarely be exceeded, unless the file is corrupt or 
-   * malicious. For more info, see:
-   *   http://msdn2.microsoft.com/en-us/library/ms724872.aspx
-   */
-  /* XXX: Should probably do something different here for this tool.
-   *      Also, It would be really nice if this message somehow included the
-   *      name of the current value we're having trouble with, since
-   *      stderr/stdout don't always sync nicely.
-   */
-  if(size > REGFI_VK_MAX_DATA_LENGTH)
-  {
-    fprintf(stderr, "WARN: value data size %d larger than "
-	    "%d, truncating...\n", size, REGFI_VK_MAX_DATA_LENGTH);
-    size = REGFI_VK_MAX_DATA_LENGTH;
-  }
-  
+
   quoted_name = quote_string(vk->valuename, key_special_chars);
   if (quoted_name == NULL)
@@ -144,6 +125,14 @@
     quoted_name[0] = '\0';
   }
-
-  quoted_value = data_to_ascii(vk->data, size, vk->type, &conv_error);
+  /* XXX: Add command line option to choose output encoding */
+  if(vk->data != NULL 
+     && !regfi_interpret_data(f, "US-ASCII//TRANSLIT", vk->type, vk->data))
+  {
+    fprintf(stderr, "WARN: Error occurred while interpreting data for VK record"
+	    " at offset 0x%.8X.\n", vk->offset);
+  }
+  printMsgs(f);
+
+  quoted_value = data_to_ascii(vk->data, &conv_error);
   if(quoted_value == NULL)
   {
@@ -469,4 +458,6 @@
     return 10;
 
+  data.buf = NULL;
+  data.len = 0;
   for(i=0; i<range_list_size(unalloc_values); i++)
   {
@@ -571,7 +562,9 @@
 	  }
 	}
-
-	vk->data = data.buf;
-	vk->data_size = data.len;
+	/* XXX: Need to come up with a different way to link these so the
+	 *      vk->data item can be removed from the structure.
+	 */
+	vk->data = regfi_buffer_to_data(data);
+	talloc_steal(vk, vk->data);
       }
     }
Index: trunk/src/reglookup.c
===================================================================
--- trunk/src/reglookup.c	(revision 158)
+++ trunk/src/reglookup.c	(revision 159)
@@ -50,25 +50,12 @@
 
 
-void printValue(const REGFI_VK_REC* vk, char* prefix)
-{
+void printValue(REGFI_ITERATOR* iter, const REGFI_VK_REC* vk, char* prefix)
+{
+  REGFI_DATA* data;
   char* quoted_value = NULL;
   char* quoted_name = NULL;
   char* conv_error = NULL;
   const char* str_type = NULL;
-  uint32 size = vk->data_size;
-
-  /* Microsoft's documentation indicates that "available memory" is 
-   * the limit on value sizes.  Annoying.  We limit it to 1M which 
-   * should rarely be exceeded, unless the file is corrupt or 
-   * malicious. For more info, see:
-   *   http://msdn2.microsoft.com/en-us/library/ms724872.aspx
-   */
-  if(size > REGFI_VK_MAX_DATA_LENGTH)
-  {
-    fprintf(stderr, "WARN: value data size %d larger than "
-	    "%d, truncating...\n", size, REGFI_VK_MAX_DATA_LENGTH);
-    size = REGFI_VK_MAX_DATA_LENGTH;
-  }
-  
+
   quoted_name = quote_string(vk->valuename, key_special_chars);
   if (quoted_name == NULL)
@@ -84,14 +71,11 @@
     quoted_name[0] = '\0';
   }
-
-  if(vk->data == NULL)
-  {
-    if(print_verbose)
-      fprintf(stderr, "INFO: While quoting value for '%s/%s', "
-	      "data pointer was NULL.\n", prefix, quoted_name);
-  }
-  else
-  {
-    quoted_value = data_to_ascii(vk->data, size, vk->type, &conv_error);
+  
+  data = regfi_iterator_fetch_data(iter, vk);
+
+  printMsgs(iter->f);
+  if(data != NULL)
+  {
+    quoted_value = data_to_ascii(data, &conv_error);
     if(quoted_value == NULL)
     {
@@ -103,7 +87,8 @@
 		"Returned error: %s\n", prefix, quoted_name, conv_error);
     }
-    else if(conv_error != NULL && print_verbose)
-      fprintf(stderr, "INFO: While quoting value for '%s/%s', "
+    else if(conv_error != NULL)
+      fprintf(stderr, "WARN: While quoting value for '%s/%s', "
 	      "warning returned: %s\n", prefix, quoted_name, conv_error);
+    regfi_free_data(data);
   }
 
@@ -281,5 +266,5 @@
   {
     if(!type_filter_enabled || (value->type == type_filter))
-      printValue(value, prefix);
+      printValue(iter, value, prefix);
     regfi_free_value(value);
     value = regfi_iterator_next_value(iter);
@@ -511,5 +496,5 @@
 
     if(!type_filter_enabled || (value->type == type_filter))
-      printValue(value, tmp_path_joined);
+      printValue(iter, value, tmp_path_joined);
 
     regfi_free_value(value);
@@ -632,5 +617,6 @@
     regfi_set_message_mask(f, REGFI_MSG_INFO|REGFI_MSG_WARN|REGFI_MSG_ERROR);
 
-  iter = regfi_iterator_new(f);
+  /* XXX: add command line option to choose output encoding */
+  iter = regfi_iterator_new(f, 0);
   if(iter == NULL)
   {
