Changeset 69 for trunk


Ignore:
Timestamp:
07/30/06 13:57:45 (18 years ago)
Author:
tim
Message:

Improved interfaces to some low-layer value formatting functions.
Better error reporting.
Added more comments.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/reglookup.c

    r66 r69  
    8383       * times the amount of input left to process.  The expansion is bounded
    8484       * below by a minimum safety increase, and above by the maximum possible
    85        * output string length.
     85       * output string length.  This should minimize both the number of
     86       * reallocs() and the amount of wasted memory.
    8687       */
    8788      added_len = (len-i)*num_written/(i+1);
     
    137138
    138139/*
    139  * Convert from Unicode to ASCII.
     140 * Convert from UTF-16LE to ASCII.  Accepts a Unicode buffer, uni, and
     141 * it's length, uni_max.  Writes ASCII to the buffer ascii, whose size
     142 * is ascii_max.  Writes at most (ascii_max-1) bytes to ascii, and null
     143 * terminates the string.  Returns the length of the string stored in
     144 * ascii.  On error, returns a negative errno code.
    140145 */
    141146static int uni_to_ascii(unsigned char* uni, char* ascii,
     
    144149  char* inbuf = (char*)uni;
    145150  char* outbuf = ascii;
     151  unsigned int out_len = ascii_max-1;
    146152  int ret;
    147153
     
    149155  conv_desc = iconv_open("US-ASCII", "UTF-16LE");
    150156
    151   ret = iconv(conv_desc, &inbuf, &uni_max, &outbuf, &ascii_max);
     157  ret = iconv(conv_desc, &inbuf, &uni_max, &outbuf, &out_len);
    152158  if(ret == -1)
    153159  {
     
    163169
    164170/*
    165  * Convert a data value to a string for display
     171 * Convert a data value to a string for display.  Returns NULL on error,
     172 * and the string to display if there is no error, or a non-fatal
     173 * error.  On any error (fatal or non-fatal) occurs, (*error_msg) will
     174 * be set to a newly allocated string, containing an error message.  If
     175 * a memory allocation failure occurs while generating the error
     176 * message, both the return value and (*error_msg) will be NULL.  It
     177 * is the responsibility of the caller to free both a non-NULL return
     178 * value, and a non-NULL (*error_msg).
    166179 */
    167 static char* data_to_ascii(unsigned char *datap, int len, int type)
     180static char* data_to_ascii(unsigned char *datap, int len, int type,
     181                           char** error_msg)
    168182{
    169183  char* asciip;
    170   unsigned int i;
    171   unsigned short num_nulls;
    172184  char* ascii;
    173185  unsigned char* cur_str;
    174186  char* cur_ascii;
    175187  char* cur_quoted;
     188  char* tmp_err;
     189  const char* str_type;
     190  unsigned int i;
    176191  unsigned int cur_str_len;
    177192  unsigned int ascii_max, cur_str_max;
    178193  unsigned int str_rem, cur_str_rem, alen;
    179194  int ret_err;
     195  unsigned short num_nulls;
     196
     197  *error_msg = NULL;
    180198
    181199  switch (type)
     
    185203    /* REG_LINK is a symbolic link, stored as a unicode string. */
    186204  case REG_LINK:
    187     ascii_max = sizeof(char)*len;
    188     ascii = malloc(ascii_max+4);
     205    ascii_max = sizeof(char)*(len+1);
     206    ascii = malloc(ascii_max);
    189207    if(ascii == NULL)
    190208      return NULL;
     
    193211     * conversion fails, just quote it raw.
    194212     */
    195    
    196213    ret_err = uni_to_ascii(datap, ascii, len, ascii_max);
    197214    if(ret_err < 0)
    198215    {
    199       /* XXX: It would be nice if somehow we could include the name of this
    200        *      value in the error message.
    201        */
    202       if(print_verbose)
    203         fprintf(stderr, "VERBOSE: Unicode conversion failed; "
    204                 "printing as binary.  Error: %s\n", strerror(-ret_err));
    205 
     216      tmp_err = strerror(-ret_err);
     217      str_type = regfio_type_val2str(type);
     218      *error_msg = (char*)malloc(65+strlen(str_type)+strlen(tmp_err)+1);
     219      if(*error_msg == NULL)
     220        return NULL;
     221      sprintf(*error_msg, "Unicode conversion failed on %s field; "
     222               "printing as binary.  Error: %s", str_type, tmp_err);
     223     
    206224      cur_quoted = quote_buffer(datap, len, common_special_chars);
    207225    }
     
    238256   */
    239257  case REG_MULTI_SZ:
    240     ascii_max = sizeof(char)*len*4;
    241     cur_str_max = sizeof(char)*len+1;
     258    ascii_max = sizeof(char)*(len*4+1);
     259    cur_str_max = sizeof(char)*(len+1);
    242260    cur_str = malloc(cur_str_max);
    243261    cur_ascii = malloc(cur_str_max);
    244     ascii = malloc(ascii_max+4);
     262    ascii = malloc(ascii_max);
    245263    if(ascii == NULL || cur_str == NULL || cur_ascii == NULL)
    246264      return NULL;
     
    271289        if(ret_err < 0)
    272290        {
    273           /* XXX: It would be nice if somehow we could include the name of this
    274            *      value in the error message.
    275            */
    276           if(print_verbose)
    277             fprintf(stderr, "VERBOSE: Unicode conversion failed on sub-field; "
    278                     "printing as binary.  Error: %s\n", strerror(-ret_err));
    279          
     291          /* XXX: should every sub-field error be enumerated? */
     292          if(*error_msg == NULL)
     293          {
     294            tmp_err = strerror(-ret_err);
     295            *error_msg = (char*)malloc(90+strlen(tmp_err)+1);
     296            if(*error_msg == NULL)
     297              return NULL;
     298            sprintf(*error_msg, "Unicode conversion failed on at least one "
     299                    "MULTI_SZ sub-field; printing as binary.  Error: %s",
     300                    tmp_err);
     301          }
    280302          cur_quoted = quote_buffer(cur_str, cur_str_len-1,
    281303                                    subfield_special_chars);
     
    435457  char* quoted_value = NULL;
    436458  char* quoted_name = NULL;
     459  char* conv_error = NULL;
    437460
    438461  /* Thanks Microsoft for making this process so straight-forward!!! */
     
    446469    if(size > 4)
    447470      size = 4;
    448     quoted_value = data_to_ascii(tmp_buf, 4, vk->type);
     471    quoted_value = data_to_ascii(tmp_buf, 4, vk->type, &conv_error);
    449472  }
    450473  else
     
    461484    }
    462485
    463     quoted_value = data_to_ascii(vk->data, vk->data_size, vk->type);
     486    quoted_value = data_to_ascii(vk->data, vk->data_size,
     487                                 vk->type, &conv_error);
    464488  }
    465489 
     
    469493   */
    470494  quoted_name = quote_string(vk->valuename, common_special_chars);
     495
     496  if(quoted_value == NULL)
     497  {
     498    if(conv_error == NULL)
     499      fprintf(stderr, "ERROR: Could not quote value for '%s/%s'.  "
     500              "Memory allocation failure likely.\n", prefix, quoted_name);
     501    else
     502      fprintf(stderr, "ERROR: Could not quote value for '%s/%s'.  "
     503              "Returned error: %s\n", prefix, quoted_name, conv_error);
     504  }
     505  /* XXX: should these always be printed? */
     506  else if(conv_error != NULL && print_verbose)
     507      fprintf(stderr, "VERBOSE: While quoting value for '%s/%s', "
     508              "warning returned: %s\n", prefix, quoted_name, conv_error);
     509
    471510  if(print_security)
    472511    printf("%s/%s,%s,%s,,,,,\n", prefix, quoted_name,
     
    480519  if(quoted_name != NULL)
    481520    free(quoted_name);
     521  if(conv_error != NULL)
     522    free(conv_error);
    482523}
    483524
     
    752793          " [-p <PATH_FILTER>] [-t <TYPE_FILTER>]"
    753794          " <REGISTRY_FILE>\n");
    754   /* XXX: replace version string with Subversion property? */
    755795  fprintf(stderr, "Version: 0.3.0\n");
    756796  fprintf(stderr, "Options:\n");
Note: See TracChangeset for help on using the changeset viewer.