Changeset 101 for trunk


Ignore:
Timestamp:
03/28/08 20:46:37 (16 years ago)
Author:
tim
Message:

rewrote VK record and data cell parsing

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/regfi.h

    r99 r101  
    66 * Windows NT registry I/O library
    77 *
    8  * Copyright (C) 2005-2007 Timothy D. Morgan
     8 * Copyright (C) 2005-2008 Timothy D. Morgan
    99 * Copyright (C) 2005 Gerald (Jerry) Carter
    1010 *
     
    8484
    8585#define REGF_OFFSET_NONE        0xffffffff
    86 #define REGFI_NK_MIN_LENGTH     0x50
     86#define REGFI_NK_MIN_LENGTH     0x4C
     87#define REGFI_VK_MIN_LENGTH     0x14
    8788
    8889/* Flags for the vk records */
     
    9798#define NK_TYPE_NORMALKEY       0x0020
    9899#define NK_TYPE_ROOTKEY         0x002c
     100  /* TODO: Unknown type that shows up in Vista registries */
     101#define NK_TYPE_UNKNOWN1         0x1020
    99102
    100103#define HBIN_STORE_REF(x, y) { x->hbin = y; y->ref_count++ };
     
    152155typedef struct
    153156{
     157  uint32 offset;        /* Real offset of this record's cell in the file */
     158  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
     159
    154160  REGF_HBIN* hbin;      /* pointer to HBIN record (in memory) containing
    155161                         * this nk record
    156162                         */
     163  uint8* data;
     164  uint16 name_length;
    157165  char*  valuename;
    158   uint8* data;
    159166  uint32 hbin_off;      /* offset from beginning of this hbin block */
    160   uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
    161   uint32 rec_off;       /* offset stored in the value list */
    162167 
    163168  uint32 data_size;
    164   uint32 data_off;
     169  uint32 data_off;      /* offset of data cell (virtual) */
    165170  uint32 type;
    166   uint8  header[REC_HDR_SIZE];
     171  uint8  magic[REC_HDR_SIZE];
    167172  uint16 flag;
     173  uint16 unknown1;
    168174} REGF_VK_REC;
    169175
     
    204210
    205211  /* link in the other records here */
    206   REGF_VK_REC* values;
     212  REGF_VK_REC** values;
    207213  REGF_SK_REC* sec_desc;
    208214  REGF_LF_REC subkeys;
     
    211217  /* XXX: should we be looking for types other than the root key type? */
    212218  uint16 key_type;     
    213   uint8  header[REC_HDR_SIZE];
     219  uint8  magic[REC_HDR_SIZE];
    214220  NTTIME mtime;
    215221  uint16 name_length;
     
    374380/****************/
    375381
     382REGF_VK_REC* regfi_parse_vk(REGF_FILE* file, uint32 offset,
     383                            uint32 max_size, bool strict);
     384uint8* regfi_parse_data(REGF_FILE* file, uint32 offset,
     385                        uint32 length, bool strict);
     386
    376387
    377388#endif  /* _REGFI_H */
  • trunk/lib/regfi.c

    r99 r101  
    337337
    338338
     339/*****************************************************************************
     340 * This function is just like read(2), except that it continues to
     341 * re-try reading from the file descriptor if EINTR or EAGAIN is received. 
     342 * regfi_read will attempt to read length bytes from fd and write them to buf.
     343 *
     344 * On success, 0 is returned.  Upon failure, an errno code is returned.
     345 *
     346 * The number of bytes successfully read is returned through the length
     347 * parameter by reference.  If both the return value and length parameter are
     348 * returned as 0, then EOF was encountered immediately
     349 *****************************************************************************/
     350uint32 regfi_read(int fd, uint8* buf, uint32* length)
     351{
     352  uint32 rsize = 0;
     353  uint32 rret = 0;
     354
     355  do
     356  {
     357    rret = read(fd, buf + rsize, *length - rsize);
     358    if(rret > 0)
     359      rsize += rret;
     360  }while(*length - rsize > 0
     361         && (rret > 0 || (rret == -1 && (errno == EAGAIN || errno == EINTR))));
     362 
     363  *length = rsize;
     364  if (rret == -1 && errno != EINTR && errno != EAGAIN)
     365    return errno;
     366
     367  return 0;
     368}
     369
     370
     371/*****************************************************************************
     372 *
     373 *****************************************************************************/
     374static bool regfi_parse_cell(int fd, uint32 offset, uint8* hdr, uint32 hdr_len,
     375                             uint32* cell_length, bool* unalloc)
     376{
     377  uint32 length;
     378  int32 raw_length;
     379  uint8 tmp[4];
     380
     381  if(lseek(fd, offset, SEEK_SET) == -1)
     382    return false;
     383
     384  length = 4;
     385  if((regfi_read(fd, tmp, &length) != 0) || length != 4)
     386    return false;
     387  raw_length = IVALS(tmp, 0);
     388
     389  if(hdr_len > 0)
     390  {
     391    length = hdr_len;
     392    if((regfi_read(fd, hdr, &length) != 0) || length != hdr_len)
     393      return false;
     394  }
     395
     396  if(raw_length < 0)
     397  {
     398    (*cell_length) = raw_length*(-1);
     399    (*unalloc) = false;
     400  }
     401  else
     402  {
     403    (*cell_length) = raw_length;
     404    (*unalloc) = true;
     405  }
     406
     407  return true;
     408}
     409
     410
    339411/*******************************************************************
    340  Input a randon offset and receive the correpsonding HBIN
     412 Input a random offset and receive the correpsonding HBIN
    341413 block for it
    342414*******************************************************************/
     
    448520                 lf->header, sizeof(lf->header)))
    449521    return false;
    450                
     522
     523  /*fprintf(stdout, "DEBUG: lf->header=%c%c\n", lf->header[0], lf->header[1]);*/
     524
    451525  if ( !prs_uint16( "num_keys", &hbin->ps, depth, &lf->num_keys))
    452526    return false;
     
    524598}
    525599
    526 
    527 /*******************************************************************
    528  *******************************************************************/
    529 static bool hbin_prs_vk_rec( const char *desc, REGF_HBIN *hbin, int depth,
    530                              REGF_VK_REC *vk, REGF_FILE *file )
    531 {
    532   uint32 offset;
    533   uint16 name_length;
    534   prs_struct *ps = &hbin->ps;
    535   uint32 data_size, start_off, end_off;
    536 
    537   depth++;
    538 
    539   /* backup and get the data_size */
    540        
    541   if ( !prs_set_offset( &hbin->ps, hbin->ps.data_offset-sizeof(uint32)) )
    542     return false;
    543   start_off = hbin->ps.data_offset;
    544   if ( !prs_uint32( "cell_size", &hbin->ps, depth, &vk->cell_size ))
    545     return false;
    546 
    547   if ( !prs_uint8s("header", ps, depth, vk->header, sizeof( vk->header )) )
    548     return false;
    549 
    550   if ( !hbin->ps.io )
    551     name_length = strlen(vk->valuename);
    552 
    553   if ( !prs_uint16( "name_length", ps, depth, &name_length ))
    554     return false;
    555   if ( !prs_uint32( "data_size", ps, depth, &vk->data_size ))
    556     return false;
    557   if ( !prs_uint32( "data_off", ps, depth, &vk->data_off ))
    558     return false;
    559   if ( !prs_uint32( "type", ps, depth, &vk->type))
    560     return false;
    561   if ( !prs_uint16( "flag", ps, depth, &vk->flag))
    562     return false;
    563 
    564   offset = ps->data_offset;
    565   offset += 2;  /* skip 2 bytes */
    566   prs_set_offset( ps, offset );
    567 
    568   /* get the name */
    569 
    570   if ( vk->flag&VK_FLAG_NAME_PRESENT ) {
    571 
    572     if ( hbin->ps.io ) {
    573       if ( !(vk->valuename = (char*)zcalloc(sizeof(char), name_length+1 )))
    574         return false;
    575     }
    576     if ( !prs_uint8s("name", ps, depth,
    577                      (uint8*)vk->valuename, name_length) )
    578       return false;
    579   }
    580 
    581   end_off = hbin->ps.data_offset;
    582 
    583   /* get the data if necessary */
    584 
    585   if ( vk->data_size != 0 )
    586   {
    587     /* the data is stored in the offset if the size <= 4 */
    588     if ( !(vk->data_size & VK_DATA_IN_OFFSET) )
    589     {
    590       REGF_HBIN *hblock = hbin;
    591       uint32 data_rec_size;
    592 
    593       if ( hbin->ps.io )
    594       {
    595         if ( !(vk->data = (uint8*)zcalloc(sizeof(uint8), vk->data_size) ) )
    596           return false;
    597       }
    598 
    599       /* this data can be in another hbin */
    600       if ( !hbin_contains_offset( hbin, vk->data_off ) )
    601       {
    602         if ( !(hblock = lookup_hbin_block( file, vk->data_off )) )
    603           return false;
    604       }
    605       if (!(prs_set_offset(&hblock->ps,
    606                            (vk->data_off
    607                             + HBIN_MAGIC_SIZE
    608                             - hblock->first_hbin_off)
    609                            - sizeof(uint32))))
    610       { return false; }
    611 
    612       if ( !hblock->ps.io )
    613       {
    614         data_rec_size = ( (vk->data_size+sizeof(uint32)) & 0xfffffff8 ) + 8;
    615         data_rec_size = ( data_rec_size - 1 ) ^ 0xFFFFFFFF;
    616       }
    617       if ( !prs_uint32( "data_rec_size", &hblock->ps, depth, &data_rec_size ))
    618         return false;
    619       if(!prs_uint8s("data", &hblock->ps, depth,
    620                      vk->data, vk->data_size))
    621         return false;
    622 
    623     }
    624     else
    625     {
    626       if(!(vk->data = zcalloc(sizeof(uint8), 4)))
    627         return false;
    628       SIVAL( vk->data, 0, vk->data_off );
    629     }
    630                
    631   }
    632 
    633   /* data_size must be divisible by 8 and large enough to hold the original record */
    634 
    635   data_size = ((start_off - end_off ) & 0xfffffff8 );
    636   /* XXX: should probably print a warning here */
    637   /*if ( data_size !=  vk->cell_size )
    638     DEBUG(10,("prs_vk_rec: data_size check failed (0x%x < 0x%x)\n", data_size, vk->cell_size));*/
    639 
    640   return true;
    641 }
    642600
    643601
     
    646604 in the prs_struct *ps.
    647605*******************************************************************/
    648 static bool hbin_prs_vk_records(const char *desc, REGF_HBIN *hbin,
    649                                 int depth, REGF_NK_REC *nk, REGF_FILE *file)
     606static bool hbin_prs_vk_records(const char* desc, REGF_HBIN* hbin,
     607                                int depth, REGF_NK_REC* nk, REGF_FILE* file)
    650608{
    651609  int i;
    652   uint32 record_size;
     610  uint32 record_size, vk_raw_offset, vk_offset, vk_max_length;
     611  REGF_HBIN* sub_hbin;
    653612
    654613  depth++;
     
    660619  if(hbin->ps.io)
    661620  {
    662     if (!(nk->values = (REGF_VK_REC*)zcalloc(sizeof(REGF_VK_REC),
     621    if (!(nk->values = (REGF_VK_REC**)zcalloc(sizeof(REGF_VK_REC*),
    663622                                              nk->num_values )))
    664623      return false;
     
    684643  for ( i=0; i<nk->num_values; i++ )
    685644  {
    686     if ( !prs_uint32( "vk_off", &hbin->ps, depth, &nk->values[i].rec_off ) )
     645    if ( !prs_uint32( "vk_off", &hbin->ps, depth, &vk_raw_offset) )
    687646      return false;
    688   }
    689 
    690   for ( i=0; i<nk->num_values; i++ )
    691   {
    692     REGF_HBIN *sub_hbin = hbin;
    693     uint32 new_offset;
    694        
    695     if ( !hbin_contains_offset( hbin, nk->values[i].rec_off ) )
     647   
     648    if(hbin_contains_offset(hbin, vk_raw_offset))
     649      sub_hbin = hbin;
     650    else
    696651    {
    697       sub_hbin = lookup_hbin_block( file, nk->values[i].rec_off );
    698       if ( !sub_hbin )
     652      sub_hbin = lookup_hbin_block( file, vk_raw_offset );
     653      if (!sub_hbin)
    699654        return false;
    700655    }
    701656       
    702     new_offset = nk->values[i].rec_off
    703       + HBIN_MAGIC_SIZE
    704       - sub_hbin->first_hbin_off;
    705 
    706     if (!prs_set_offset(&sub_hbin->ps, new_offset))
    707       return false;
    708     if (!hbin_prs_vk_rec("vk_rec", sub_hbin, depth, &nk->values[i], file))
     657    vk_offset =  vk_raw_offset + REGF_BLOCKSIZE;
     658    vk_max_length = sub_hbin->block_size - vk_offset + sizeof(uint32);
     659    if((nk->values[i] = regfi_parse_vk(file, vk_offset, vk_max_length, true))
     660        == NULL)
    709661      return false;
    710662  }
     
    762714  nk_max_length = hbin->block_size - hbin->ps.data_offset + sizeof(uint32);
    763715  if ((nk = regfi_parse_nk(file, nk_cell_offset, nk_max_length, true)) == NULL)
    764     return NULL;
     716  {
     717fprintf(stderr, "DEBUG: regfi_parse_nk returned NULL!\n");
     718    return NULL;
     719  }
    765720
    766721  /* fill in values */
     
    1040995    for(i=0; i < nk->num_values; i++)
    1041996    {
    1042       if(nk->values[i].valuename != NULL)
    1043         free(nk->values[i].valuename);
    1044       if(nk->values[i].data != NULL)
    1045         free(nk->values[i].data);
     997      if(nk->values[i]->valuename != NULL)
     998        free(nk->values[i]->valuename);
     999      if(nk->values[i]->data != NULL)
     1000        free(nk->values[i]->data);
     1001      free(nk->values[i]);
    10461002    }
    10471003    free(nk->values);
     
    13521308  REGF_VK_REC* ret_val = NULL;
    13531309  if(i->cur_value < i->cur_key->num_values)
    1354     ret_val = &(i->cur_key->values[i->cur_value]);
     1310    ret_val = i->cur_key->values[i->cur_value];
    13551311
    13561312  return ret_val;
     
    16031559
    16041560
     1561
    16051562REGF_NK_REC* regfi_parse_nk(REGF_FILE* file, uint32 offset,
    16061563                            uint32 max_size, bool strict)
     
    16091566  REGF_NK_REC* ret_val;
    16101567  uint32 length;
    1611   if(lseek(file->fd, offset, SEEK_SET) == -1)
    1612     return NULL;
    1613 
    1614   length = REGFI_NK_MIN_LENGTH;
    1615   if((regfi_read(file->fd, nk_header, &length) != 0)
    1616      || length != REGFI_NK_MIN_LENGTH)
    1617     return NULL;
     1568  uint32 cell_length;
     1569  bool unalloc = false;
     1570
     1571  if(!regfi_parse_cell(file->fd, offset, nk_header, REGFI_NK_MIN_LENGTH,
     1572                       &cell_length, &unalloc))
     1573     return NULL;
    16181574 
    16191575  /* A bit of validation before bothering to allocate memory */
    1620   if(strict && ((nk_header[0x4] != 'n') || (nk_header[0x5] != 'k')))
    1621     return NULL;
     1576  if((nk_header[0x0] != 'n') || (nk_header[0x1] != 'k'))
     1577  {
     1578    /* TODO: deal with subkey-lists that reference other subkey-lists. */
     1579    /*fprintf(stderr, "DEBUG: magic check failed! \"%c%c\"\n", nk_header[0x0], nk_header[0x1]);*/
     1580    return NULL;
     1581  }
    16221582
    16231583  ret_val = (REGF_NK_REC*)zalloc(sizeof(REGF_NK_REC));
     
    16261586
    16271587  ret_val->offset = offset;
    1628   ret_val->cell_size = IVAL(nk_header, 0x0);
     1588  ret_val->cell_size = cell_length;
     1589
    16291590  if(ret_val->cell_size > max_size)
    16301591    ret_val->cell_size = max_size & 0xFFFFFFF8;
     
    16361597  }
    16371598
    1638   ret_val->header[0] = nk_header[0x4];
    1639   ret_val->header[1] = nk_header[0x5];
    1640   ret_val->key_type = SVAL(nk_header, 0x6);
    1641   if(strict && ((ret_val->key_type != NK_TYPE_NORMALKEY)
    1642                 && (ret_val->key_type != NK_TYPE_ROOTKEY)
    1643                 && (ret_val->key_type != NK_TYPE_LINKKEY)))
     1599  ret_val->magic[0] = nk_header[0x0];
     1600  ret_val->magic[1] = nk_header[0x1];
     1601  ret_val->key_type = SVAL(nk_header, 0x2);
     1602  if((ret_val->key_type != NK_TYPE_NORMALKEY)
     1603     && (ret_val->key_type != NK_TYPE_ROOTKEY)
     1604     && (ret_val->key_type != NK_TYPE_LINKKEY)
     1605     && (ret_val->key_type != NK_TYPE_UNKNOWN1))
    16441606  {
    16451607    free(ret_val);
    16461608    return NULL;
    16471609  }
    1648  
    1649   ret_val->mtime.low = IVAL(nk_header, 0x8);
    1650   ret_val->mtime.high = IVAL(nk_header, 0xC);
    1651  
    1652   ret_val->unknown1 = IVAL(nk_header, 0x10);
    1653   ret_val->parent_off = IVAL(nk_header, 0x14);
    1654   ret_val->num_subkeys = IVAL(nk_header, 0x18);
    1655   ret_val->unknown2 = IVAL(nk_header, 0x1C);
    1656   ret_val->subkeys_off = IVAL(nk_header, 0x20);
    1657   ret_val->unknown3 = IVAL(nk_header, 0x24);
    1658   ret_val->num_values = IVAL(nk_header, 0x28);
    1659   ret_val->values_off = IVAL(nk_header, 0x2C);
    1660   ret_val->sk_off = IVAL(nk_header, 0x30);
     1610
     1611  ret_val->mtime.low = IVAL(nk_header, 0x4);
     1612  ret_val->mtime.high = IVAL(nk_header, 0x8);
     1613 
     1614  ret_val->unknown1 = IVAL(nk_header, 0xC);
     1615  ret_val->parent_off = IVAL(nk_header, 0x10);
     1616  ret_val->num_subkeys = IVAL(nk_header, 0x14);
     1617  ret_val->unknown2 = IVAL(nk_header, 0x18);
     1618  ret_val->subkeys_off = IVAL(nk_header, 0x1C);
     1619  ret_val->unknown3 = IVAL(nk_header, 0x20);
     1620  ret_val->num_values = IVAL(nk_header, 0x24);
     1621  ret_val->values_off = IVAL(nk_header, 0x28);
     1622  ret_val->sk_off = IVAL(nk_header, 0x2C);
    16611623  /* TODO: currently we do nothing with class names.  Need to investigate. */
    1662   ret_val->classname_off = IVAL(nk_header, 0x34);
    1663 
    1664   ret_val->max_bytes_subkeyname = IVAL(nk_header, 0x38);
    1665   ret_val->max_bytes_subkeyclassname = IVAL(nk_header, 0x3C);
    1666   ret_val->max_bytes_valuename = IVAL(nk_header, 0x40);
    1667   ret_val->max_bytes_value = IVAL(nk_header, 0x44);
    1668   ret_val->unk_index = IVAL(nk_header, 0x48);
    1669 
    1670   ret_val->name_length = SVAL(nk_header, 0x4C);
    1671   ret_val->classname_length = SVAL(nk_header, 0x4E);
     1624  ret_val->classname_off = IVAL(nk_header, 0x30);
     1625
     1626  ret_val->max_bytes_subkeyname = IVAL(nk_header, 0x34);
     1627  ret_val->max_bytes_subkeyclassname = IVAL(nk_header, 0x38);
     1628  ret_val->max_bytes_valuename = IVAL(nk_header, 0x3C);
     1629  ret_val->max_bytes_value = IVAL(nk_header, 0x40);
     1630  ret_val->unk_index = IVAL(nk_header, 0x44);
     1631
     1632  ret_val->name_length = SVAL(nk_header, 0x48);
     1633  ret_val->classname_length = SVAL(nk_header, 0x4A);
    16721634
    16731635  if(ret_val->name_length + REGFI_NK_MIN_LENGTH > ret_val->cell_size)
    1674     ret_val->name_length = ret_val->cell_size - REGFI_NK_MIN_LENGTH;
     1636  {
     1637    if(strict)
     1638    {
     1639      free(ret_val);
     1640      return NULL;
     1641    }
     1642    else
     1643      ret_val->name_length = ret_val->cell_size - REGFI_NK_MIN_LENGTH;
     1644  }
     1645  else if (unalloc)
     1646  { /* Truncate cell_size if it's much larger than the apparent total record length. */
     1647    /* Round up to the next multiple of 8 */
     1648    length = (ret_val->name_length + REGFI_NK_MIN_LENGTH) & 0xFFFFFFF8;
     1649    if(length < ret_val->name_length + REGFI_NK_MIN_LENGTH)
     1650      length+=8;
     1651
     1652    /* If cell_size is still greater, truncate. */
     1653    if(length < ret_val->cell_size)
     1654      ret_val->cell_size = length;
     1655  }
    16751656
    16761657  ret_val->keyname = (char*)zalloc(sizeof(char)*(ret_val->name_length+1));
     
    16831664  /* Don't need to seek, should be at the right offset */
    16841665  length = ret_val->name_length;
    1685   if((regfi_read(file->fd, ret_val->keyname, &length) != 0)
     1666  if((regfi_read(file->fd, (uint8*)ret_val->keyname, &length) != 0)
    16861667     || length != ret_val->name_length)
    16871668  {
     
    16971678
    16981679
    1699 /*****************************************************************************
    1700  * This function is just like read(2), except that it continues to
    1701  * re-try reading from the file descriptor if EINTR or EAGAIN is received. 
    1702  * regfi_read will attempt to read length bytes from fd and write them to buf.
    1703  *
    1704  * On success, 0 is returned.  Upon failure, an errno code is returned.
    1705  *
    1706  * The number of bytes successfully read is returned through the length
    1707  * parameter by reference.  If both the return value and length parameter are
    1708  * returned as 0, then EOF was encountered immediately
    1709  *****************************************************************************/
    1710 uint32 regfi_read(int fd, uint8* buf, uint32* length)
    1711 {
    1712   uint32 rsize = 0;
    1713   uint32 rret = 0;
    1714 
    1715   do
    1716   {
    1717     rret = read(fd, buf + rsize, *length - rsize);
    1718     if(rret > 0)
    1719       rsize += rret;
    1720   }while(*length - rsize > 0
    1721          && (rret > 0 || (rret == -1 && (errno == EAGAIN || errno == EINTR))));
    1722  
    1723   *length = rsize;
    1724   if (rret == -1 && errno != EINTR && errno != EAGAIN)
    1725     return errno;
    1726 
    1727   return 0;
    1728 }
     1680/*******************************************************************
     1681 *******************************************************************/
     1682REGF_VK_REC* regfi_parse_vk(REGF_FILE* file, uint32 offset,
     1683                            uint32 max_size, bool strict)
     1684{
     1685  REGF_VK_REC* ret_val;
     1686  uint8 vk_header[REGFI_VK_MIN_LENGTH];
     1687  uint32 raw_data_size, length, cell_length;
     1688  bool unalloc = false;
     1689
     1690  if(!regfi_parse_cell(file->fd, offset, vk_header, REGFI_VK_MIN_LENGTH,
     1691                       &cell_length, &unalloc))
     1692    return NULL;
     1693   
     1694  ret_val = (REGF_VK_REC*)zalloc(sizeof(REGF_VK_REC));
     1695  if(ret_val == NULL)
     1696    return NULL;
     1697
     1698  ret_val->offset = offset;
     1699  ret_val->cell_size = cell_length;
     1700
     1701  if(ret_val->cell_size > max_size)
     1702    ret_val->cell_size = max_size & 0xFFFFFFF8;
     1703  if((ret_val->cell_size < REGFI_VK_MIN_LENGTH)
     1704     || (strict && ret_val->cell_size != (ret_val->cell_size & 0xFFFFFFF8)))
     1705  {
     1706    free(ret_val);
     1707    return NULL;
     1708  }
     1709
     1710  ret_val->magic[0] = vk_header[0x0];
     1711  ret_val->magic[1] = vk_header[0x1];
     1712  if((ret_val->magic[0] != 'v') || (ret_val->magic[1] != 'k'))
     1713  {
     1714    free(ret_val);
     1715    return NULL;
     1716  }
     1717
     1718  ret_val->name_length = SVAL(vk_header, 0x2);
     1719  raw_data_size = IVAL(vk_header, 0x4);
     1720  ret_val->data_size = raw_data_size & ~VK_DATA_IN_OFFSET;
     1721  ret_val->data_off = IVAL(vk_header, 0x8);
     1722  ret_val->type = IVAL(vk_header, 0xC);
     1723  ret_val->flag = SVAL(vk_header, 0x10);
     1724  ret_val->unknown1 = SVAL(vk_header, 0x12);
     1725
     1726  if(ret_val->flag & VK_FLAG_NAME_PRESENT)
     1727  {
     1728    if(ret_val->name_length + REGFI_VK_MIN_LENGTH > ret_val->cell_size)
     1729    {
     1730      if(strict)
     1731      {
     1732        free(ret_val);
     1733        return NULL;
     1734      }
     1735      else
     1736        ret_val->name_length = ret_val->cell_size - REGFI_VK_MIN_LENGTH;
     1737    }
     1738
     1739    /* Round up to the next multiple of 8 */
     1740    length = (ret_val->name_length + REGFI_NK_MIN_LENGTH) & 0xFFFFFFF8;
     1741    if(length < ret_val->name_length + REGFI_NK_MIN_LENGTH)
     1742      length+=8;
     1743
     1744    ret_val->valuename = (char*)zalloc(sizeof(char)*(ret_val->name_length+1));
     1745    if(ret_val->valuename == NULL)
     1746    {
     1747      free(ret_val);
     1748      return NULL;
     1749    }
     1750   
     1751    /* Don't need to seek, should be at the right offset */
     1752    length = ret_val->name_length;
     1753    if((regfi_read(file->fd, (uint8*)ret_val->valuename, &length) != 0)
     1754       || length != ret_val->name_length)
     1755    {
     1756      free(ret_val->valuename);
     1757      free(ret_val);
     1758      return NULL;
     1759    }
     1760    ret_val->valuename[ret_val->name_length] = '\0';
     1761  }
     1762  else
     1763    length = REGFI_VK_MIN_LENGTH;
     1764
     1765  if(unalloc)
     1766  {
     1767    /* If cell_size is still greater, truncate. */
     1768    if(length < ret_val->cell_size)
     1769      ret_val->cell_size = length;
     1770  }
     1771
     1772  if(ret_val->data_size == 0)
     1773    ret_val->data = NULL;
     1774  else
     1775  {
     1776    ret_val->data = regfi_parse_data(file, ret_val->data_off+REGF_BLOCKSIZE,
     1777                                     raw_data_size, strict);
     1778    if(strict && (ret_val->data == NULL))
     1779    {
     1780      free(ret_val->valuename);
     1781      free(ret_val);
     1782      return NULL;
     1783    }
     1784  }
     1785
     1786  return ret_val;
     1787}
     1788
     1789
     1790uint8* regfi_parse_data(REGF_FILE* file, uint32 offset, uint32 length, bool strict)
     1791{
     1792  uint8* ret_val;
     1793  uint32 read_length, cell_length;
     1794  bool unalloc;
     1795
     1796  /* The data is stored in the offset if the size <= 4 */
     1797  if (length & VK_DATA_IN_OFFSET)   
     1798  {
     1799    length = length & ~VK_DATA_IN_OFFSET;
     1800    if(length > 4)
     1801      return NULL;
     1802
     1803    if((ret_val = (uint8*)zalloc(sizeof(uint8)*length)) == NULL)
     1804      return NULL;
     1805    memcpy(ret_val, &offset, length);
     1806  }
     1807  else
     1808  {
     1809    if(!regfi_parse_cell(file->fd, offset, NULL, 0,
     1810                         &cell_length, &unalloc))
     1811      return NULL;
     1812   
     1813    if(cell_length < 8 || ((cell_length & 0xFFFFFFF8) != cell_length))
     1814      return NULL;
     1815
     1816    if(cell_length - 4 < length)
     1817    {
     1818      if(strict)
     1819        return NULL;
     1820      else
     1821        length = cell_length - 4;
     1822    }
     1823
     1824    /* TODO: There is currently no check to ensure the data
     1825     *       cell doesn't cross HBIN boundary.
     1826     */
     1827
     1828    if((ret_val = (uint8*)zalloc(sizeof(uint8)*length)) == NULL)
     1829      return NULL;
     1830
     1831    read_length = length;
     1832    if((regfi_read(file->fd, ret_val, &read_length) != 0)
     1833       || read_length != length)
     1834    {
     1835      free(ret_val);
     1836      return NULL;
     1837    }
     1838  }
     1839
     1840  return ret_val;
     1841}
Note: See TracChangeset for help on using the changeset viewer.