Changeset 127 for trunk


Ignore:
Timestamp:
09/01/08 19:20:50 (16 years ago)
Author:
tim
Message:

added preliminary support for 'ri' subkey lists.
cleaned up regfi API a bit.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/regfi.h

    r126 r127  
    8686#define REGFI_VK_MIN_LENGTH        0x14
    8787#define REGFI_SK_MIN_LENGTH        0x14
    88 #define REGFI_HASH_LIST_MIN_LENGTH 0x4
     88#define REGFI_SUBKEY_LIST_MIN_LEN 0x4
    8989
    9090/* Constants used for validation */
     
    138138
    139139
    140 /* Hash List -- list of key offsets and hashed names for consistency */
     140/* Subkey List -- list of key offsets and hashed names for consistency */
    141141typedef struct
    142142{
    143143  uint32 nk_off;
    144144  uint32 hash;
    145 } REGF_HASH_LIST_ELEM;
     145} REGF_SUBKEY_LIST_ELEM;
    146146
    147147
     
    150150  uint32 offset;        /* Real offset of this record's cell in the file */
    151151  uint32 cell_size;      /* ((start_offset - end_offset) & 0xfffffff8) */
    152   REGF_HBIN* hbin;       /* pointer to HBIN record (in memory) containing
    153                           * this nk record
    154                           */
    155   uint32 hbin_off;       /* offset from beginning of this hbin block */
    156   REGF_HASH_LIST_ELEM* hashes;
     152  uint32 num_keys;
     153  REGF_SUBKEY_LIST_ELEM* elements;
    157154 
    158155  uint8 magic[REC_HDR_SIZE];
    159   uint16 num_keys;
    160 } REGF_HASH_LIST;
     156} REGF_SUBKEY_LIST;
    161157
    162158
     
    219215  /* link in the other records here */
    220216  REGF_VK_REC** values;
    221   REGF_HASH_LIST* subkeys;
     217  REGF_SUBKEY_LIST* subkeys;
    222218 
    223219  /* header information */
     
    246242  /* children */
    247243  uint32 num_subkeys;
    248   uint32 subkeys_off;   /* hash records that point to NK records */     
     244  uint32 subkeys_off;   /* offset of subkey list that points to NK records */
    249245  uint32 num_values;
    250246  uint32 values_off;    /* value lists which point to VK records */
    251   uint32 sk_off;        /* offset to SK record */ 
     247  uint32 sk_off;        /* offset to SK record */
    252248} REGF_NK_REC;
    253249
     
    347343const REGF_VK_REC*    regfi_iterator_cur_value(REGFI_ITERATOR* i);
    348344const REGF_VK_REC*    regfi_iterator_next_value(REGFI_ITERATOR* i);
     345
     346
     347/********************************************************/
     348/* Middle-layer structure caching, loading, and linking */
     349/********************************************************/
     350REGF_HBIN* regfi_lookup_hbin(REGF_FILE* file, uint32 offset);
     351
     352REGF_NK_REC* regfi_load_key(REGF_FILE* file, uint32 offset, bool strict);
     353
     354REGF_SUBKEY_LIST* regfi_load_subkeylist(REGF_FILE* file, uint32 offset,
     355                                        uint32 num_keys, uint32 max_size,
     356                                        bool strict);
     357
     358REGF_VK_REC** regfi_load_valuelist(REGF_FILE* file, uint32 offset,
     359                                   uint32 num_values, uint32 max_size,
     360                                   bool strict);
     361
     362REGF_SUBKEY_LIST* regfi_merge_subkeylists(uint16 num_lists,
     363                                          REGF_SUBKEY_LIST** lists,
     364                                          bool strict);
    349365
    350366/************************************/
     
    370386                                     uint32 max_size, bool strict);
    371387
     388REGF_VK_REC* regfi_parse_vk(REGF_FILE* file, uint32 offset,
     389                            uint32 max_size, bool strict);
     390
     391uint8* regfi_parse_data(REGF_FILE* file, uint32 offset,
     392                        uint32 length, bool strict);
     393
     394REGF_SK_REC* regfi_parse_sk(REGF_FILE* file, uint32 offset, uint32 max_size, bool strict);
     395
     396range_list* regfi_parse_unalloc_cells(REGF_FILE* file);
     397
     398bool regfi_parse_cell(int fd, uint32 offset, uint8* hdr, uint32 hdr_len,
     399                      uint32* cell_length, bool* unalloc);
     400
     401char* regfi_parse_classname(REGF_FILE* file, uint32 offset,
     402                            uint16* name_length, bool strict);
     403
    372404
    373405/* Private Functions */
    374406REGF_NK_REC*          regfi_rootkey(REGF_FILE* file);
    375407void                  regfi_key_free(REGF_NK_REC* nk);
     408void                  regfi_subkeylist_free(REGF_SUBKEY_LIST* list);
    376409uint32                regfi_read(int fd, uint8* buf, uint32* length);
    377410
    378411
    379 
    380 /****************/
    381 /* Experimental */
    382 /****************/
    383 REGF_NK_REC* regfi_load_key(REGF_FILE* file, uint32 offset, bool strict);
    384 
    385 REGF_HASH_LIST* regfi_load_hashlist(REGF_FILE* file, uint32 offset,
    386                                     uint32 num_keys, uint32 max_size,
    387                                     bool strict);
    388 
    389 REGF_VK_REC** regfi_load_valuelist(REGF_FILE* file, uint32 offset,
    390                                    uint32 num_values, uint32 max_size,
    391                                    bool strict);
    392 
    393 REGF_VK_REC* regfi_parse_vk(REGF_FILE* file, uint32 offset,
    394                             uint32 max_size, bool strict);
    395 
    396 uint8* regfi_parse_data(REGF_FILE* file, uint32 offset,
    397                         uint32 length, bool strict);
    398 
    399 REGF_SK_REC* regfi_parse_sk(REGF_FILE* file, uint32 offset, uint32 max_size, bool strict);
    400 
    401 range_list* regfi_parse_unalloc_cells(REGF_FILE* file);
    402 
    403 REGF_HBIN* regfi_lookup_hbin(REGF_FILE* file, uint32 offset);
    404 
    405 bool regfi_parse_cell(int fd, uint32 offset, uint8* hdr, uint32 hdr_len,
    406                       uint32* cell_length, bool* unalloc);
    407 
    408 char* regfi_parse_classname(REGF_FILE* file, uint32 offset,
    409                             uint16* name_length, bool strict);
    410 
    411412#endif  /* _REGFI_H */
  • trunk/lib/regfi.c

    r126 r127  
    440440
    441441
    442 
    443442/*******************************************************************
    444443 *******************************************************************/
    445 REGF_HASH_LIST* regfi_load_hashlist(REGF_FILE* file, uint32 offset,
    446                                     uint32 num_keys, uint32 max_size,
    447                                     bool strict)
    448 {
    449   REGF_HASH_LIST* ret_val;
    450   uint32 i, cell_length, length;
     444REGF_SUBKEY_LIST* regfi_merge_subkeylists(uint16 num_lists,
     445                                          REGF_SUBKEY_LIST** lists,
     446                                          bool strict)
     447{
     448  uint32 i,j,k;
     449  REGF_SUBKEY_LIST* ret_val = (REGF_SUBKEY_LIST*)zalloc(sizeof(REGF_SUBKEY_LIST));
     450  if(ret_val == NULL || lists == NULL)
     451    return NULL;
     452 
     453  /* Obtain total number of elements */
     454  ret_val->num_keys = 0;
     455  for(i=0; i < num_lists; i++)
     456  {
     457    if(lists[i] == NULL)
     458    {
     459      ret_val->num_keys = 0;
     460      break;
     461    }
     462    ret_val->num_keys += lists[i]->num_keys;
     463  }
     464 
     465  if(ret_val->num_keys > 0)
     466  {
     467    ret_val->elements =
     468      (REGF_SUBKEY_LIST_ELEM*)zalloc(sizeof(REGF_SUBKEY_LIST_ELEM)
     469                                     * ret_val->num_keys);
     470    k=0;
     471    if(ret_val->elements != NULL)
     472    {
     473      for(i=0; i<num_lists; i++)
     474        for(j=0; j<lists[i]->num_keys; j++)
     475        {
     476          ret_val->elements[k].hash=lists[i]->elements[j].hash;
     477          ret_val->elements[k++].nk_off=lists[i]->elements[j].nk_off;
     478        }
     479    }
     480  }
     481 
     482  for(i=0; i < num_lists; i++)
     483    regfi_subkeylist_free(lists[i]);
     484  free(lists);
     485
     486  return ret_val;
     487}
     488
     489
     490
     491/*******************************************************************
     492 *******************************************************************/
     493REGF_SUBKEY_LIST* regfi_load_subkeylist(REGF_FILE* file, uint32 offset,
     494                                        uint32 num_keys, uint32 max_size,
     495                                        bool strict)
     496{
     497  REGF_SUBKEY_LIST* ret_val;
     498  REGF_SUBKEY_LIST** sublists;
     499  REGF_HBIN* sublist_hbin;
     500  uint32 i, cell_length, length, num_sublists, off, max_length;
    451501  uint8* hashes;
    452   uint8 buf[REGFI_HASH_LIST_MIN_LENGTH];
     502  uint8 buf[REGFI_SUBKEY_LIST_MIN_LEN];
    453503  bool unalloc;
    454504
    455   if(!regfi_parse_cell(file->fd, offset, buf, REGFI_HASH_LIST_MIN_LENGTH,
     505  if(!regfi_parse_cell(file->fd, offset, buf, REGFI_SUBKEY_LIST_MIN_LEN,
    456506                       &cell_length, &unalloc))
    457507    return NULL;
    458508
    459   ret_val = (REGF_HASH_LIST*)zalloc(sizeof(REGF_HASH_LIST));
    460   if(ret_val == NULL)
    461     return NULL;
    462 
    463   ret_val->offset = offset;
    464509  if(cell_length > max_size)
    465510  {
     
    468513    cell_length = max_size & 0xFFFFFFF8;
    469514  }
     515
     516  if(buf[0] == 'r' && buf[1] == 'i')
     517  {
     518    num_sublists = SVAL(buf, 0x2);
     519
     520    /* XXX: check cell_length vs num_sublists vs max_length */
     521    length = num_sublists*sizeof(uint32);
     522    hashes = (uint8*)zalloc(length);
     523    if(hashes == NULL)
     524      return NULL;
     525
     526    if(regfi_read(file->fd, hashes, &length) != 0
     527       || length != num_sublists*sizeof(uint32))
     528    {
     529      free(hashes);
     530      return NULL;
     531    }
     532
     533    sublists = (REGF_SUBKEY_LIST**)zalloc(num_sublists*sizeof(REGF_SUBKEY_LIST*));   
     534    for(i=0; i < num_sublists; i++)
     535    {
     536      off = IVAL(hashes, i*4)+REGF_BLOCKSIZE;
     537      sublist_hbin = regfi_lookup_hbin(file, IVAL(hashes, i*4));
     538      max_length = sublist_hbin->block_size + sublist_hbin->file_off - off;
     539
     540      /* XXX: Need to add a recursion depth limit of some kind. */
     541      sublists[i] = regfi_load_subkeylist(file, off, 0, max_length, strict);
     542    }
     543
     544    return regfi_merge_subkeylists(num_sublists, sublists, strict);
     545  }
     546
     547  ret_val = (REGF_SUBKEY_LIST*)zalloc(sizeof(REGF_SUBKEY_LIST));
     548  if(ret_val == NULL)
     549    return NULL;
     550
     551  ret_val->offset = offset;
    470552  ret_val->cell_size = cell_length;
    471553
    472   if((buf[0] != 'l' || buf[1] != 'f') && (buf[0] != 'l' || buf[1] != 'h')
    473      && (buf[0] != 'r' || buf[1] != 'i'))
     554  if((buf[0] != 'l' || buf[1] != 'f') && (buf[0] != 'l' || buf[1] != 'h'))
    474555  {
    475556    /*printf("DEBUG: lf->header=%c%c\n", buf[0], buf[1]);*/
     
    478559  }
    479560
    480   if(buf[0] == 'r' && buf[1] == 'i')
    481   {
    482     fprintf(stderr, "WARNING: ignoring encountered \"ri\" record.\n");
    483     free(ret_val);
    484     return NULL;
    485   }
    486 
    487561  ret_val->magic[0] = buf[0];
    488562  ret_val->magic[1] = buf[1];
     
    491565  if(num_keys != ret_val->num_keys)
    492566  {
    493     if(strict)
    494     {
    495       free(ret_val);
    496       return NULL;
    497     }
    498     /* XXX: Not sure which should be authoritative, the number from the
    499      *      NK record, or the number in the hash list.  Go with the larger
    500      *      of the two to ensure all keys are found.  Note the length checks
    501      *      on the cell later ensure that there won't be any critical errors.
     567    /*  Not sure which should be authoritative, the number from the
     568     *  NK record, or the number in the subkey list.  Go with the larger
     569     *  of the two to ensure all keys are found, since in 'ri' records,
     570     *  there is no authoritative parent count for a leaf subkey list. 
     571     *  Note the length checks on the cell later ensure that there won't
     572     *  be any critical errors.
    502573     */
    503574    if(num_keys < ret_val->num_keys)
     
    507578  }
    508579
    509   if(cell_length - REGFI_HASH_LIST_MIN_LENGTH - sizeof(uint32)
    510      < ret_val->num_keys*sizeof(REGF_HASH_LIST_ELEM))
    511     return NULL;
    512 
    513   length = sizeof(REGF_HASH_LIST_ELEM)*ret_val->num_keys;
    514   ret_val->hashes = (REGF_HASH_LIST_ELEM*)zalloc(length);
    515   if(ret_val->hashes == NULL)
     580  if(cell_length - REGFI_SUBKEY_LIST_MIN_LEN - sizeof(uint32)
     581     < ret_val->num_keys*sizeof(REGF_SUBKEY_LIST_ELEM))
     582    return NULL;
     583
     584  length = sizeof(REGF_SUBKEY_LIST_ELEM)*ret_val->num_keys;
     585  ret_val->elements = (REGF_SUBKEY_LIST_ELEM*)zalloc(length);
     586  if(ret_val->elements == NULL)
    516587  {
    517588    free(ret_val);
     
    522593  if(hashes == NULL)
    523594  {
    524     free(ret_val->hashes);
     595    free(ret_val->elements);
    525596    free(ret_val);
    526597    return NULL;
     
    528599
    529600  if(regfi_read(file->fd, hashes, &length) != 0
    530      || length != sizeof(REGF_HASH_LIST_ELEM)*ret_val->num_keys)
    531   {
    532     free(ret_val->hashes);
     601     || length != sizeof(REGF_SUBKEY_LIST_ELEM)*ret_val->num_keys)
     602  {
     603    free(ret_val->elements);
    533604    free(ret_val);
    534605    return NULL;
     
    537608  for (i=0; i < ret_val->num_keys; i++)
    538609  {
    539     ret_val->hashes[i].nk_off = IVAL(hashes, i*sizeof(REGF_HASH_LIST_ELEM));
    540     ret_val->hashes[i].hash = IVAL(hashes, i*sizeof(REGF_HASH_LIST_ELEM)+4);
     610    ret_val->elements[i].nk_off = IVAL(hashes, i*sizeof(REGF_SUBKEY_LIST_ELEM));
     611    ret_val->elements[i].hash = IVAL(hashes, i*sizeof(REGF_SUBKEY_LIST_ELEM)+4);
    541612  }
    542613  free(hashes);
     
    818889      off = nk->subkeys_off + REGF_BLOCKSIZE;
    819890      max_length = sub_hbin->block_size + sub_hbin->file_off - off;
    820       nk->subkeys = regfi_load_hashlist(file, off, nk->num_subkeys,
    821                                         max_length, true);
     891      nk->subkeys = regfi_load_subkeylist(file, off, nk->num_subkeys,
     892                                          max_length, true);
    822893      if(nk->subkeys == NULL)
    823894      {
     
    10031074  }
    10041075
     1076  regfi_subkeylist_free(nk->subkeys);
     1077
    10051078  if(nk->keyname != NULL)
    10061079    free(nk->keyname);
     
    10111084  /* XXX: not freeing sec_desc because these are cached.  This needs to be reviewed. */
    10121085  free(nk);
     1086}
     1087
     1088
     1089/******************************************************************************
     1090 *****************************************************************************/
     1091void regfi_subkeylist_free(REGF_SUBKEY_LIST* list)
     1092{
     1093  if(list != NULL)
     1094  {
     1095    free(list->elements);
     1096    free(list);
     1097  }
    10131098}
    10141099
     
    12691354    return NULL;
    12701355
    1271   nk_offset = i->cur_key->subkeys->hashes[i->cur_subkey].nk_off;
     1356  nk_offset = i->cur_key->subkeys->elements[i->cur_subkey].nk_off;
    12721357 
    12731358  return regfi_load_key(i->f, nk_offset+REGF_BLOCKSIZE, true);
Note: See TracChangeset for help on using the changeset viewer.