Changeset 31 for trunk/lib/regfio.c


Ignore:
Timestamp:
07/16/05 15:05:19 (19 years ago)
Author:
tim
Message:

Added new lightweight stack library

rewrote test program to use this instead of string concatenation/recursion.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/regfio.c

    r30 r31  
    3737
    3838/*******************************************************************
    39 *******************************************************************/
     39 *******************************************************************/
    4040static int read_block( REGF_FILE *file, prs_struct *ps, uint32 file_offset,
    4141                       uint32 block_size )
    4242{
    43         int bytes_read, returned;
    44         char *buffer;
    45         SMB_STRUCT_STAT sbuf;
    46 
    47         /* check for end of file */
    48 
    49         if ( fstat( file->fd, &sbuf ) ) {
    50                 DEBUG(0,("read_block: stat() failed! (%s)\n", strerror(errno)));
    51                 return -1;
    52         }
    53 
    54         if ( (size_t)file_offset >= sbuf.st_size )
    55                 return -1;
    56        
    57         /* if block_size == 0, we are parsnig HBIN records and need
    58            to read some of the header to get the block_size from there */
     43  int bytes_read, returned;
     44  char *buffer;
     45  SMB_STRUCT_STAT sbuf;
     46
     47  /* check for end of file */
     48
     49  if ( fstat( file->fd, &sbuf ) ) {
     50    /*DEBUG(0,("read_block: stat() failed! (%s)\n", strerror(errno)));*/
     51    return -1;
     52  }
     53
     54  if ( (size_t)file_offset >= sbuf.st_size )
     55    return -1;
     56       
     57  /* if block_size == 0, we are parsnig HBIN records and need
     58     to read some of the header to get the block_size from there */
    5959           
    60         if ( block_size == 0 ) {
    61                 uint8 hdr[0x20];
    62 
    63                 if ( lseek( file->fd, file_offset, SEEK_SET ) == -1 ) {
    64                         DEBUG(0,("read_block: lseek() failed! (%s)\n", strerror(errno) ));
    65                         return -1;
    66                 }
    67 
    68                 returned = read( file->fd, hdr, 0x20 );
    69                 if ( (returned == -1) || (returned < 0x20) ) {
    70                         DEBUG(0,("read_block: failed to read in HBIN header. Is the file corrupt?\n"));
    71                         return -1;
    72                 }
    73 
    74                 /* make sure this is an hbin header */
    75 
    76                 if ( strncmp( hdr, "hbin", HBIN_HDR_SIZE ) != 0 ) {
    77                         DEBUG(0,("read_block: invalid block header!\n"));
    78                         return -1;
    79                 }
    80 
    81                 block_size = IVAL( hdr, 0x08 );
    82         }
    83 
    84         DEBUG(10,("read_block: block_size == 0x%x\n", block_size ));
    85 
    86         /* set the offset, initialize the buffer, and read the block from disk */
    87 
    88         if ( lseek( file->fd, file_offset, SEEK_SET ) == -1 ) {
    89                 DEBUG(0,("read_block: lseek() failed! (%s)\n", strerror(errno) ));
    90                 return -1;
    91         }
    92        
    93         prs_init( ps, block_size, file->mem_ctx, UNMARSHALL );
    94         buffer = ps->data_p;
    95         bytes_read = returned = 0;
    96 
    97         while ( bytes_read < block_size ) {
    98                 if ( (returned = read( file->fd, buffer+bytes_read, block_size-bytes_read )) == -1 ) {
    99                         DEBUG(0,("read_block: read() failed (%s)\n", strerror(errno) ));
    100                         return false;
    101                 }
    102                 if ( (returned == 0) && (bytes_read < block_size) ) {
    103                         DEBUG(0,("read_block: not a vald registry file ?\n" ));
    104                         return false;
    105                 }       
    106                
    107                 bytes_read += returned;
    108         }
    109        
    110         return bytes_read;
    111 }
    112 
    113 
    114 /*******************************************************************
    115 *******************************************************************/
     60  if ( block_size == 0 ) {
     61    uint8 hdr[0x20];
     62
     63    if ( lseek( file->fd, file_offset, SEEK_SET ) == -1 ) {
     64      /*DEBUG(0,("read_block: lseek() failed! (%s)\n", strerror(errno) ));*/
     65      return -1;
     66    }
     67
     68    returned = read( file->fd, hdr, 0x20 );
     69    if ( (returned == -1) || (returned < 0x20) ) {
     70      /*DEBUG(0,("read_block: failed to read in HBIN header. Is the file corrupt?\n"));*/
     71      return -1;
     72    }
     73
     74    /* make sure this is an hbin header */
     75
     76    if ( strncmp( hdr, "hbin", HBIN_HDR_SIZE ) != 0 ) {
     77      /*DEBUG(0,("read_block: invalid block header!\n"));*/
     78      return -1;
     79    }
     80
     81    block_size = IVAL( hdr, 0x08 );
     82  }
     83
     84  /*DEBUG(10,("read_block: block_size == 0x%x\n", block_size ));*/
     85
     86  /* set the offset, initialize the buffer, and read the block from disk */
     87
     88  if ( lseek( file->fd, file_offset, SEEK_SET ) == -1 ) {
     89    /*DEBUG(0,("read_block: lseek() failed! (%s)\n", strerror(errno) ));*/
     90    return -1;
     91  }
     92       
     93  prs_init( ps, block_size, file->mem_ctx, UNMARSHALL );
     94  buffer = ps->data_p;
     95  bytes_read = returned = 0;
     96
     97  while ( bytes_read < block_size ) {
     98    if ( (returned = read( file->fd, buffer+bytes_read, block_size-bytes_read )) == -1 ) {
     99      /*DEBUG(0,("read_block: read() failed (%s)\n", strerror(errno) ));*/
     100      return false;
     101    }
     102    if ( (returned == 0) && (bytes_read < block_size) ) {
     103      /*DEBUG(0,("read_block: not a vald registry file ?\n" ));*/
     104      return false;
     105    }   
     106               
     107    bytes_read += returned;
     108  }
     109       
     110  return bytes_read;
     111}
     112
     113
     114/*******************************************************************
     115 *******************************************************************/
    116116static bool prs_regf_block( const char *desc, prs_struct *ps, int depth, REGF_FILE *file )
    117117{
    118         depth++;
    119        
    120         if ( !prs_uint8s( true, "header", ps, depth, file->header, sizeof( file->header )) )
    121                 return false;
    122        
    123         /* yes, these values are always identical so store them only once */
    124        
    125         if ( !prs_uint32( "unknown1", ps, depth, &file->unknown1 ))
    126                 return false;
    127         if ( !prs_uint32( "unknown1 (again)", ps, depth, &file->unknown1 ))
    128                 return false;
    129 
    130         /* get the modtime */
    131        
    132         if ( !prs_set_offset( ps, 0x0c ) )
    133                 return false;
    134         if ( !smb_io_time( "modtime", &file->mtime, ps, depth ) )
    135                 return false;
    136 
    137         /* constants */
    138        
    139         if ( !prs_uint32( "unknown2", ps, depth, &file->unknown2 ))
    140                 return false;
    141         if ( !prs_uint32( "unknown3", ps, depth, &file->unknown3 ))
    142                 return false;
    143         if ( !prs_uint32( "unknown4", ps, depth, &file->unknown4 ))
    144                 return false;
    145         if ( !prs_uint32( "unknown5", ps, depth, &file->unknown5 ))
    146                 return false;
    147 
    148         /* get file offsets */
    149        
    150         if ( !prs_set_offset( ps, 0x24 ) )
    151                 return false;
    152         if ( !prs_uint32( "data_offset", ps, depth, &file->data_offset ))
    153                 return false;
    154         if ( !prs_uint32( "last_block", ps, depth, &file->last_block ))
    155                 return false;
    156                
    157         /* one more constant */
    158        
    159         if ( !prs_uint32( "unknown6", ps, depth, &file->unknown6 ))
    160                 return false;
    161                
    162         /* get the checksum */
    163        
    164         if ( !prs_set_offset( ps, 0x01fc ) )
    165                 return false;
    166         if ( !prs_uint32( "checksum", ps, depth, &file->checksum ))
    167                 return false;
    168        
    169         return true;
    170 }
    171 
    172 
    173 /*******************************************************************
    174 *******************************************************************/
     118  depth++;
     119       
     120  if ( !prs_uint8s( true, "header", ps, depth, file->header, sizeof( file->header )) )
     121    return false;
     122       
     123  /* yes, these values are always identical so store them only once */
     124       
     125  if ( !prs_uint32( "unknown1", ps, depth, &file->unknown1 ))
     126    return false;
     127  if ( !prs_uint32( "unknown1 (again)", ps, depth, &file->unknown1 ))
     128    return false;
     129
     130  /* get the modtime */
     131       
     132  if ( !prs_set_offset( ps, 0x0c ) )
     133    return false;
     134  if ( !smb_io_time( "modtime", &file->mtime, ps, depth ) )
     135    return false;
     136
     137  /* constants */
     138       
     139  if ( !prs_uint32( "unknown2", ps, depth, &file->unknown2 ))
     140    return false;
     141  if ( !prs_uint32( "unknown3", ps, depth, &file->unknown3 ))
     142    return false;
     143  if ( !prs_uint32( "unknown4", ps, depth, &file->unknown4 ))
     144    return false;
     145  if ( !prs_uint32( "unknown5", ps, depth, &file->unknown5 ))
     146    return false;
     147
     148  /* get file offsets */
     149       
     150  if ( !prs_set_offset( ps, 0x24 ) )
     151    return false;
     152  if ( !prs_uint32( "data_offset", ps, depth, &file->data_offset ))
     153    return false;
     154  if ( !prs_uint32( "last_block", ps, depth, &file->last_block ))
     155    return false;
     156               
     157  /* one more constant */
     158       
     159  if ( !prs_uint32( "unknown6", ps, depth, &file->unknown6 ))
     160    return false;
     161               
     162  /* get the checksum */
     163       
     164  if ( !prs_set_offset( ps, 0x01fc ) )
     165    return false;
     166  if ( !prs_uint32( "checksum", ps, depth, &file->checksum ))
     167    return false;
     168       
     169  return true;
     170}
     171
     172
     173/*******************************************************************
     174 *******************************************************************/
    175175static bool prs_hbin_block( const char *desc, prs_struct *ps, int depth, REGF_HBIN *hbin )
    176176{
    177         uint32 block_size2;
    178 
    179         depth++;
    180        
    181         if ( !prs_uint8s( true, "header", ps, depth, hbin->header, sizeof( hbin->header )) )
    182                 return false;
    183 
    184         if ( !prs_uint32( "first_hbin_off", ps, depth, &hbin->first_hbin_off ))
    185                 return false;
    186 
    187         /* The dosreg.cpp comments say that the block size is at 0x1c.
    188            According to a WINXP NTUSER.dat file, this is wrong.  The block_size
    189            is at 0x08 */
    190 
    191         if ( !prs_uint32( "block_size", ps, depth, &hbin->block_size ))
    192                 return false;
    193 
    194         block_size2 = hbin->block_size;
    195         prs_set_offset( ps, 0x1c );
    196         if ( !prs_uint32( "block_size2", ps, depth, &block_size2 ))
    197                 return false;
    198 
    199         if ( !ps->io )
    200                 hbin->dirty = true;
    201        
    202 
    203         return true;
    204 }
    205 
    206 
    207 /*******************************************************************
    208 *******************************************************************/
     177  uint32 block_size2;
     178
     179  depth++;
     180       
     181  if ( !prs_uint8s( true, "header", ps, depth, hbin->header, sizeof( hbin->header )) )
     182    return false;
     183
     184  if ( !prs_uint32( "first_hbin_off", ps, depth, &hbin->first_hbin_off ))
     185    return false;
     186
     187  /* The dosreg.cpp comments say that the block size is at 0x1c.
     188     According to a WINXP NTUSER.dat file, this is wrong.  The block_size
     189     is at 0x08 */
     190
     191  if ( !prs_uint32( "block_size", ps, depth, &hbin->block_size ))
     192    return false;
     193
     194  block_size2 = hbin->block_size;
     195  prs_set_offset( ps, 0x1c );
     196  if ( !prs_uint32( "block_size2", ps, depth, &block_size2 ))
     197    return false;
     198
     199  if ( !ps->io )
     200    hbin->dirty = true;
     201       
     202
     203  return true;
     204}
     205
     206
     207/*******************************************************************
     208 *******************************************************************/
    209209static bool prs_nk_rec( const char *desc, prs_struct *ps, int depth, REGF_NK_REC *nk )
    210210{
    211         uint16 class_length, name_length;
    212         uint32 start;
    213         uint32 data_size, start_off, end_off;
    214         uint32 unknown_off = REGF_OFFSET_NONE;
    215 
    216         nk->hbin_off = ps->data_offset;
    217         start = nk->hbin_off;
    218        
    219         depth++;
    220        
    221         /* back up and get the data_size */
    222        
    223         if ( !prs_set_offset( ps, ps->data_offset-sizeof(uint32)) )
    224                 return false;
    225         start_off = ps->data_offset;
    226         if ( !prs_uint32( "rec_size", ps, depth, &nk->rec_size ))
    227                 return false;
    228        
    229         if ( !prs_uint8s( true, "header", ps, depth, nk->header, sizeof( nk->header )) )
    230                 return false;
    231                
    232         if ( !prs_uint16( "key_type", ps, depth, &nk->key_type ))
    233                 return false;
    234         if ( !smb_io_time( "mtime", &nk->mtime, ps, depth ))
    235                 return false;
    236                
    237         if ( !prs_set_offset( ps, start+0x0010 ) )
    238                 return false;
    239         if ( !prs_uint32( "parent_off", ps, depth, &nk->parent_off ))
    240                 return false;
    241         if ( !prs_uint32( "num_subkeys", ps, depth, &nk->num_subkeys ))
    242                 return false;
    243                
    244         if ( !prs_set_offset( ps, start+0x001c ) )
    245                 return false;
    246         if ( !prs_uint32( "subkeys_off", ps, depth, &nk->subkeys_off ))
    247                 return false;
    248         if ( !prs_uint32( "unknown_off", ps, depth, &unknown_off) )
    249                 return false;
    250                
    251         if ( !prs_set_offset( ps, start+0x0024 ) )
    252                 return false;
    253         if ( !prs_uint32( "num_values", ps, depth, &nk->num_values ))
    254                 return false;
    255         if ( !prs_uint32( "values_off", ps, depth, &nk->values_off ))
    256                 return false;
    257         if ( !prs_uint32( "sk_off", ps, depth, &nk->sk_off ))
    258                 return false;
    259         if ( !prs_uint32( "classname_off", ps, depth, &nk->classname_off ))
    260                 return false;
    261 
    262         if ( !prs_uint32( "max_bytes_subkeyname", ps, depth, &nk->max_bytes_subkeyname))
    263                 return false;
    264         if ( !prs_uint32( "max_bytes_subkeyclassname", ps, depth, &nk->max_bytes_subkeyclassname))
    265                 return false;
    266         if ( !prs_uint32( "max_bytes_valuename", ps, depth, &nk->max_bytes_valuename))
    267                 return false;
    268         if ( !prs_uint32( "max_bytes_value", ps, depth, &nk->max_bytes_value))
    269                 return false;
    270         if ( !prs_uint32( "unknown index", ps, depth, &nk->unk_index))
    271                 return false;
    272 
    273         name_length = nk->keyname ? strlen(nk->keyname) : 0 ;
    274         class_length = nk->classname ? strlen(nk->classname) : 0 ;
    275         if ( !prs_uint16( "name_length", ps, depth, &name_length ))
    276                 return false;
    277         if ( !prs_uint16( "class_length", ps, depth, &class_length ))
    278                 return false;   
    279                
    280         if ( class_length ) {
    281                 ;;
    282         }
    283        
    284         if ( name_length ) {
    285                 if ( ps->io ) {
    286                   if ( !(nk->keyname = (char*)zcalloc(sizeof(char), name_length+1 )) )
    287                                 return false;
    288                 }
    289 
    290                 if ( !prs_uint8s( true, "name", ps, depth, nk->keyname, name_length) )
    291                         return false;
    292 
    293                 if ( ps->io )
    294                         nk->keyname[name_length] = '\0';
    295         }
    296 
    297         end_off = ps->data_offset;
    298 
    299         /* data_size must be divisible by 8 and large enough to hold the original record */
    300 
    301         data_size = ((start_off - end_off) & 0xfffffff8 );
    302         if ( data_size > nk->rec_size )
    303                 DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, nk->rec_size));
    304 
    305         if ( !ps->io )
    306                 nk->hbin->dirty = true;
    307 
    308         return true;
    309 }
    310 
    311 
    312 /*******************************************************************
    313 *******************************************************************/
     211  uint16 class_length, name_length;
     212  uint32 start;
     213  uint32 data_size, start_off, end_off;
     214  uint32 unknown_off = REGF_OFFSET_NONE;
     215
     216  nk->hbin_off = ps->data_offset;
     217  start = nk->hbin_off;
     218       
     219  depth++;
     220       
     221  /* back up and get the data_size */
     222       
     223  if ( !prs_set_offset( ps, ps->data_offset-sizeof(uint32)) )
     224    return false;
     225  start_off = ps->data_offset;
     226  if ( !prs_uint32( "rec_size", ps, depth, &nk->rec_size ))
     227    return false;
     228       
     229  if ( !prs_uint8s( true, "header", ps, depth, nk->header, sizeof( nk->header )) )
     230    return false;
     231               
     232  if ( !prs_uint16( "key_type", ps, depth, &nk->key_type ))
     233    return false;
     234  if ( !smb_io_time( "mtime", &nk->mtime, ps, depth ))
     235    return false;
     236               
     237  if ( !prs_set_offset( ps, start+0x0010 ) )
     238    return false;
     239  if ( !prs_uint32( "parent_off", ps, depth, &nk->parent_off ))
     240    return false;
     241  if ( !prs_uint32( "num_subkeys", ps, depth, &nk->num_subkeys ))
     242    return false;
     243               
     244  if ( !prs_set_offset( ps, start+0x001c ) )
     245    return false;
     246  if ( !prs_uint32( "subkeys_off", ps, depth, &nk->subkeys_off ))
     247    return false;
     248  if ( !prs_uint32( "unknown_off", ps, depth, &unknown_off) )
     249    return false;
     250               
     251  if ( !prs_set_offset( ps, start+0x0024 ) )
     252    return false;
     253  if ( !prs_uint32( "num_values", ps, depth, &nk->num_values ))
     254    return false;
     255  if ( !prs_uint32( "values_off", ps, depth, &nk->values_off ))
     256    return false;
     257  if ( !prs_uint32( "sk_off", ps, depth, &nk->sk_off ))
     258    return false;
     259  if ( !prs_uint32( "classname_off", ps, depth, &nk->classname_off ))
     260    return false;
     261
     262  if ( !prs_uint32( "max_bytes_subkeyname", ps, depth, &nk->max_bytes_subkeyname))
     263    return false;
     264  if ( !prs_uint32( "max_bytes_subkeyclassname", ps, depth, &nk->max_bytes_subkeyclassname))
     265    return false;
     266  if ( !prs_uint32( "max_bytes_valuename", ps, depth, &nk->max_bytes_valuename))
     267    return false;
     268  if ( !prs_uint32( "max_bytes_value", ps, depth, &nk->max_bytes_value))
     269    return false;
     270  if ( !prs_uint32( "unknown index", ps, depth, &nk->unk_index))
     271    return false;
     272
     273  name_length = nk->keyname ? strlen(nk->keyname) : 0 ;
     274  class_length = nk->classname ? strlen(nk->classname) : 0 ;
     275  if ( !prs_uint16( "name_length", ps, depth, &name_length ))
     276    return false;
     277  if ( !prs_uint16( "class_length", ps, depth, &class_length ))
     278    return false;       
     279               
     280  if ( class_length ) {
     281    ;;
     282  }
     283       
     284  if ( name_length ) {
     285    if ( ps->io ) {
     286      if ( !(nk->keyname = (char*)zcalloc(sizeof(char), name_length+1 )) )
     287        return false;
     288    }
     289
     290    if ( !prs_uint8s( true, "name", ps, depth, nk->keyname, name_length) )
     291      return false;
     292
     293    if ( ps->io )
     294      nk->keyname[name_length] = '\0';
     295  }
     296
     297  end_off = ps->data_offset;
     298
     299  /* data_size must be divisible by 8 and large enough to hold the original record */
     300
     301  data_size = ((start_off - end_off) & 0xfffffff8 );
     302  if ( data_size > nk->rec_size )
     303    /*DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, nk->rec_size));*/
     304
     305    if ( !ps->io )
     306      nk->hbin->dirty = true;
     307
     308  return true;
     309}
     310
     311
     312/*******************************************************************
     313 *******************************************************************/
    314314static uint32 regf_block_checksum( prs_struct *ps )
    315315{
    316         char *buffer = ps->data_p;
    317         uint32 checksum, x;
    318         int i;
    319 
    320         /* XOR of all bytes 0x0000 - 0x01FB */
    321                
    322         checksum = x = 0;
    323        
    324         for ( i=0; i<0x01FB; i+=4 ) {
    325                 x = IVAL(buffer, i );
    326                 checksum ^= x;
    327         }
    328        
    329         return checksum;
    330 }
    331 
    332 
    333 /*******************************************************************
    334 *******************************************************************/
     316  char *buffer = ps->data_p;
     317  uint32 checksum, x;
     318  int i;
     319
     320  /* XOR of all bytes 0x0000 - 0x01FB */
     321               
     322  checksum = x = 0;
     323       
     324  for ( i=0; i<0x01FB; i+=4 ) {
     325    x = IVAL(buffer, i );
     326    checksum ^= x;
     327  }
     328       
     329  return checksum;
     330}
     331
     332
     333/*******************************************************************
     334 *******************************************************************/
    335335static bool read_regf_block( REGF_FILE *file )
    336336{
    337         prs_struct ps;
    338         uint32 checksum;
    339        
    340         /* grab the first block from the file */
    341                
    342         if ( read_block( file, &ps, 0, REGF_BLOCKSIZE ) == -1 )
    343                 return false;
    344        
    345         /* parse the block and verify the checksum */
    346        
    347         if ( !prs_regf_block( "regf_header", &ps, 0, file ) )
    348                 return false;   
    349                
    350         checksum = regf_block_checksum( &ps );
    351        
    352         if(ps.is_dynamic)
    353           SAFE_FREE(ps.data_p);
    354         ps.is_dynamic = false;
    355         ps.buffer_size = 0;
    356         ps.data_offset = 0;
    357 
    358         if ( file->checksum !=  checksum ) {
    359                 DEBUG(0,("read_regf_block: invalid checksum\n" ));
    360                 return false;
    361         }
    362 
    363         return true;
    364 }
    365 
    366 
    367 /*******************************************************************
    368 *******************************************************************/
     337  prs_struct ps;
     338  uint32 checksum;
     339       
     340  /* grab the first block from the file */
     341               
     342  if ( read_block( file, &ps, 0, REGF_BLOCKSIZE ) == -1 )
     343    return false;
     344       
     345  /* parse the block and verify the checksum */
     346       
     347  if ( !prs_regf_block( "regf_header", &ps, 0, file ) )
     348    return false;       
     349               
     350  checksum = regf_block_checksum( &ps );
     351       
     352  if(ps.is_dynamic)
     353    SAFE_FREE(ps.data_p);
     354  ps.is_dynamic = false;
     355  ps.buffer_size = 0;
     356  ps.data_offset = 0;
     357
     358  if ( file->checksum !=  checksum ) {
     359    /*DEBUG(0,("read_regf_block: invalid checksum\n" ));*/
     360    return false;
     361  }
     362
     363  return true;
     364}
     365
     366
     367/*******************************************************************
     368 *******************************************************************/
    369369static REGF_HBIN* read_hbin_block( REGF_FILE *file, off_t offset )
    370370{
    371         REGF_HBIN *hbin;
    372         uint32 record_size, curr_off, block_size, header;
    373        
    374         if ( !(hbin = (REGF_HBIN*)zalloc(sizeof(REGF_HBIN))) )
    375                 return NULL;
    376         hbin->file_off = offset;
    377         hbin->free_off = -1;
    378                
    379         if ( read_block( file, &hbin->ps, offset, 0 ) == -1 )
    380                 return NULL;
    381        
    382         if ( !prs_hbin_block( "hbin", &hbin->ps, 0, hbin ) )
    383                 return NULL;   
    384 
    385         /* this should be the same thing as hbin->block_size but just in case */
    386 
    387         block_size = hbin->ps.buffer_size;
    388 
    389         /* Find the available free space offset.  Always at the end,
    390            so walk the record list and stop when you get to the end.
    391            The end is defined by a record header of 0xffffffff.  The
    392            previous 4 bytes contains the amount of free space remaining
    393            in the hbin block. */
    394 
    395         /* remember that the record_size is in the 4 bytes preceeding the record itself */
    396 
    397         if ( !prs_set_offset( &hbin->ps, file->data_offset+HBIN_HDR_SIZE-sizeof(uint32) ) )
    398                 return false;
    399 
    400         record_size = 0;
    401         curr_off = hbin->ps.data_offset;
    402         while ( header != 0xffffffff ) {
    403                 /* not done yet so reset the current offset to the
    404                    next record_size field */
    405 
    406                 curr_off = curr_off+record_size;
    407 
    408                 /* for some reason the record_size of the last record in
    409                    an hbin block can extend past the end of the block
    410                    even though the record fits within the remaining
    411                    space....aaarrrgggghhhhhh */
    412 
    413                 if ( curr_off >= block_size ) {
    414                         record_size = -1;
    415                         curr_off = -1;
    416                         break;
    417                 }
    418 
    419                 if ( !prs_set_offset( &hbin->ps, curr_off) )
    420                         return false;
    421 
    422                 if ( !prs_uint32( "rec_size", &hbin->ps, 0, &record_size ) )
    423                         return false;
    424                 if ( !prs_uint32( "header", &hbin->ps, 0, &header ) )
    425                         return false;
    426                
    427                 assert( record_size != 0 );
    428 
    429                 if ( record_size & 0x80000000 ) {
    430                         /* absolute_value(record_size) */
    431                         record_size = (record_size ^ 0xffffffff) + 1;
    432                 }
    433         }
    434 
    435         /* save the free space offset */
    436 
    437         if ( header == 0xffffffff ) {
    438 
    439                 /* account for the fact that the curr_off is 4 bytes behind the actual
    440                    record header */
    441 
    442                 hbin->free_off = curr_off + sizeof(uint32);
    443                 hbin->free_size = record_size;
    444         }
    445 
    446         DEBUG(10,("read_hbin_block: free space offset == 0x%x\n", hbin->free_off));
    447 
    448         if ( !prs_set_offset( &hbin->ps, file->data_offset+HBIN_HDR_SIZE )  )
    449                 return false;
    450        
    451         return hbin;
     371  REGF_HBIN *hbin;
     372  uint32 record_size, curr_off, block_size, header;
     373       
     374  if ( !(hbin = (REGF_HBIN*)zalloc(sizeof(REGF_HBIN))) )
     375    return NULL;
     376  hbin->file_off = offset;
     377  hbin->free_off = -1;
     378               
     379  if ( read_block( file, &hbin->ps, offset, 0 ) == -1 )
     380    return NULL;
     381       
     382  if ( !prs_hbin_block( "hbin", &hbin->ps, 0, hbin ) )
     383    return NULL;       
     384
     385  /* this should be the same thing as hbin->block_size but just in case */
     386
     387  block_size = hbin->ps.buffer_size;
     388
     389  /* Find the available free space offset.  Always at the end,
     390     so walk the record list and stop when you get to the end.
     391     The end is defined by a record header of 0xffffffff.  The
     392     previous 4 bytes contains the amount of free space remaining
     393     in the hbin block. */
     394
     395  /* remember that the record_size is in the 4 bytes preceeding the record itself */
     396
     397  if ( !prs_set_offset( &hbin->ps, file->data_offset+HBIN_HDR_SIZE-sizeof(uint32) ) )
     398    return false;
     399
     400  record_size = 0;
     401  curr_off = hbin->ps.data_offset;
     402  while ( header != 0xffffffff ) {
     403    /* not done yet so reset the current offset to the
     404       next record_size field */
     405
     406    curr_off = curr_off+record_size;
     407
     408    /* for some reason the record_size of the last record in
     409       an hbin block can extend past the end of the block
     410       even though the record fits within the remaining
     411       space....aaarrrgggghhhhhh */
     412
     413    if ( curr_off >= block_size ) {
     414      record_size = -1;
     415      curr_off = -1;
     416      break;
     417    }
     418
     419    if ( !prs_set_offset( &hbin->ps, curr_off) )
     420      return false;
     421
     422    if ( !prs_uint32( "rec_size", &hbin->ps, 0, &record_size ) )
     423      return false;
     424    if ( !prs_uint32( "header", &hbin->ps, 0, &header ) )
     425      return false;
     426               
     427    assert( record_size != 0 );
     428
     429    if ( record_size & 0x80000000 ) {
     430      /* absolute_value(record_size) */
     431      record_size = (record_size ^ 0xffffffff) + 1;
     432    }
     433  }
     434
     435  /* save the free space offset */
     436
     437  if ( header == 0xffffffff ) {
     438
     439    /* account for the fact that the curr_off is 4 bytes behind the actual
     440       record header */
     441
     442    hbin->free_off = curr_off + sizeof(uint32);
     443    hbin->free_size = record_size;
     444  }
     445
     446  /*DEBUG(10,("read_hbin_block: free space offset == 0x%x\n", hbin->free_off));*/
     447
     448  if ( !prs_set_offset( &hbin->ps, file->data_offset+HBIN_HDR_SIZE )  )
     449    return false;
     450       
     451  return hbin;
    452452}
    453453
     
    459459static bool hbin_contains_offset( REGF_HBIN *hbin, uint32 offset )
    460460{
    461         if ( !hbin )
    462                 return false;
    463        
    464         if ( (offset > hbin->first_hbin_off) && (offset < (hbin->first_hbin_off+hbin->block_size)) )
    465                 return true;
    466                
    467         return false;
     461  if ( !hbin )
     462    return false;
     463       
     464  if ( (offset > hbin->first_hbin_off) && (offset < (hbin->first_hbin_off+hbin->block_size)) )
     465    return true;
     466               
     467  return false;
    468468}
    469469
     
    475475static REGF_HBIN* lookup_hbin_block( REGF_FILE *file, uint32 offset )
    476476{
    477         REGF_HBIN *hbin = NULL;
    478         uint32 block_off;
    479 
    480         /* start with the open list */
    481 
    482         for ( hbin=file->block_list; hbin; hbin=hbin->next ) {
    483                 DEBUG(10,("lookup_hbin_block: address = 0x%x [0x%x]\n", hbin->file_off, (uint32)hbin ));
    484                 if ( hbin_contains_offset( hbin, offset ) )
    485                         return hbin;
    486         }
    487        
    488         if ( !hbin ) {
    489                 /* start at the beginning */
    490 
    491                 block_off = REGF_BLOCKSIZE;
    492                 do {
    493                         /* cleanup before the next round */
    494                         if ( hbin )
    495                         {
    496                           if(hbin->ps.is_dynamic)
    497                             SAFE_FREE(hbin->ps.data_p);
    498                           hbin->ps.is_dynamic = false;
    499                           hbin->ps.buffer_size = 0;
    500                           hbin->ps.data_offset = 0;
    501                         }
    502 
    503                         hbin = read_hbin_block( file, block_off );
    504 
    505                         if ( hbin )
    506                                 block_off = hbin->file_off + hbin->block_size;
    507 
    508                 } while ( hbin && !hbin_contains_offset( hbin, offset ) );
    509         }
    510 
    511         if ( hbin )
    512                 DLIST_ADD( file->block_list, hbin );
    513 
    514         return hbin;
    515 }
    516 
    517 
    518 /*******************************************************************
    519 *******************************************************************/
     477  REGF_HBIN *hbin = NULL;
     478  uint32 block_off;
     479
     480  /* start with the open list */
     481
     482  for ( hbin=file->block_list; hbin; hbin=hbin->next ) {
     483    /* DEBUG(10,("lookup_hbin_block: address = 0x%x [0x%x]\n", hbin->file_off, (uint32)hbin ));*/
     484    if ( hbin_contains_offset( hbin, offset ) )
     485      return hbin;
     486  }
     487       
     488  if ( !hbin ) {
     489    /* start at the beginning */
     490
     491    block_off = REGF_BLOCKSIZE;
     492    do {
     493      /* cleanup before the next round */
     494      if ( hbin )
     495      {
     496        if(hbin->ps.is_dynamic)
     497          SAFE_FREE(hbin->ps.data_p);
     498        hbin->ps.is_dynamic = false;
     499        hbin->ps.buffer_size = 0;
     500        hbin->ps.data_offset = 0;
     501      }
     502
     503      hbin = read_hbin_block( file, block_off );
     504
     505      if ( hbin )
     506        block_off = hbin->file_off + hbin->block_size;
     507
     508    } while ( hbin && !hbin_contains_offset( hbin, offset ) );
     509  }
     510
     511  if ( hbin )
     512    DLIST_ADD( file->block_list, hbin );
     513
     514  return hbin;
     515}
     516
     517
     518/*******************************************************************
     519 *******************************************************************/
    520520static bool prs_hash_rec( const char *desc, prs_struct *ps, int depth, REGF_HASH_REC *hash )
    521521{
    522         depth++;
    523 
    524         if ( !prs_uint32( "nk_off", ps, depth, &hash->nk_off ))
    525                 return false;
    526         if ( !prs_uint8s( true, "keycheck", ps, depth, hash->keycheck, sizeof( hash->keycheck )) )
    527                 return false;
    528        
    529         return true;
    530 }
    531 
    532 
    533 /*******************************************************************
    534 *******************************************************************/
     522  depth++;
     523
     524  if ( !prs_uint32( "nk_off", ps, depth, &hash->nk_off ))
     525    return false;
     526  if ( !prs_uint8s( true, "keycheck", ps, depth, hash->keycheck, sizeof( hash->keycheck )) )
     527    return false;
     528       
     529  return true;
     530}
     531
     532
     533/*******************************************************************
     534 *******************************************************************/
    535535static bool hbin_prs_lf_records( const char *desc, REGF_HBIN *hbin, int depth, REGF_NK_REC *nk )
    536536{
    537         int i;
    538         REGF_LF_REC *lf = &nk->subkeys;
    539         uint32 data_size, start_off, end_off;
    540 
    541         depth++;
    542 
    543         /* check if we have anything to do first */
    544        
    545         if ( nk->num_subkeys == 0 )
    546                 return true;
    547 
    548         /* move to the LF record */
    549 
    550         if ( !prs_set_offset( &hbin->ps, nk->subkeys_off + HBIN_HDR_SIZE - hbin->first_hbin_off ) )
    551                 return false;
    552 
    553         /* backup and get the data_size */
    554        
    555         if ( !prs_set_offset( &hbin->ps, hbin->ps.data_offset-sizeof(uint32)) )
    556                 return false;
    557         start_off = hbin->ps.data_offset;
    558         if ( !prs_uint32( "rec_size", &hbin->ps, depth, &lf->rec_size ))
    559                 return false;
    560 
    561         if ( !prs_uint8s( true, "header", &hbin->ps, depth, lf->header, sizeof( lf->header )) )
    562                 return false;
    563                
    564         if ( !prs_uint16( "num_keys", &hbin->ps, depth, &lf->num_keys))
    565                 return false;
    566 
    567         if ( hbin->ps.io ) {
    568           if ( !(lf->hashes = (REGF_HASH_REC*)zcalloc(sizeof(REGF_HASH_REC), lf->num_keys )) )
    569                         return false;
    570         }
    571 
    572         for ( i=0; i<lf->num_keys; i++ ) {
    573                 if ( !prs_hash_rec( "hash_rec", &hbin->ps, depth, &lf->hashes[i] ) )
    574                         return false;
    575         }
    576 
    577         end_off = hbin->ps.data_offset;
    578 
    579         /* data_size must be divisible by 8 and large enough to hold the original record */
    580 
    581         data_size = ((start_off - end_off) & 0xfffffff8 );
    582         if ( data_size > lf->rec_size )
    583                 DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, lf->rec_size));
    584 
    585         if ( !hbin->ps.io )
    586                 hbin->dirty = true;
    587 
    588         return true;
    589 }
    590 
    591 
    592 /*******************************************************************
    593 *******************************************************************/
     537  int i;
     538  REGF_LF_REC *lf = &nk->subkeys;
     539  uint32 data_size, start_off, end_off;
     540
     541  depth++;
     542
     543  /* check if we have anything to do first */
     544       
     545  if ( nk->num_subkeys == 0 )
     546    return true;
     547
     548  /* move to the LF record */
     549
     550  if ( !prs_set_offset( &hbin->ps, nk->subkeys_off + HBIN_HDR_SIZE - hbin->first_hbin_off ) )
     551    return false;
     552
     553  /* backup and get the data_size */
     554       
     555  if ( !prs_set_offset( &hbin->ps, hbin->ps.data_offset-sizeof(uint32)) )
     556    return false;
     557  start_off = hbin->ps.data_offset;
     558  if ( !prs_uint32( "rec_size", &hbin->ps, depth, &lf->rec_size ))
     559    return false;
     560
     561  if ( !prs_uint8s( true, "header", &hbin->ps, depth, lf->header, sizeof( lf->header )) )
     562    return false;
     563               
     564  if ( !prs_uint16( "num_keys", &hbin->ps, depth, &lf->num_keys))
     565    return false;
     566
     567  if ( hbin->ps.io ) {
     568    if ( !(lf->hashes = (REGF_HASH_REC*)zcalloc(sizeof(REGF_HASH_REC), lf->num_keys )) )
     569      return false;
     570  }
     571
     572  for ( i=0; i<lf->num_keys; i++ ) {
     573    if ( !prs_hash_rec( "hash_rec", &hbin->ps, depth, &lf->hashes[i] ) )
     574      return false;
     575  }
     576
     577  end_off = hbin->ps.data_offset;
     578
     579  /* data_size must be divisible by 8 and large enough to hold the original record */
     580
     581  data_size = ((start_off - end_off) & 0xfffffff8 );
     582  if ( data_size > lf->rec_size )
     583    /*DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, lf->rec_size));*/
     584
     585    if ( !hbin->ps.io )
     586      hbin->dirty = true;
     587
     588  return true;
     589}
     590
     591
     592/*******************************************************************
     593 *******************************************************************/
    594594static bool hbin_prs_sk_rec( const char *desc, REGF_HBIN *hbin, int depth, REGF_SK_REC *sk )
    595595{
    596         prs_struct *ps = &hbin->ps;
    597         uint16 tag = 0xFFFF;
    598         uint32 data_size, start_off, end_off;
    599 
    600 
    601         depth++;
    602 
    603         if ( !prs_set_offset( &hbin->ps, sk->sk_off + HBIN_HDR_SIZE - hbin->first_hbin_off ) )
    604                 return false;
    605 
    606         /* backup and get the data_size */
    607        
    608         if ( !prs_set_offset( &hbin->ps, hbin->ps.data_offset-sizeof(uint32)) )
    609                 return false;
    610         start_off = hbin->ps.data_offset;
    611         if ( !prs_uint32( "rec_size", &hbin->ps, depth, &sk->rec_size ))
    612                 return false;
    613 
    614         if ( !prs_uint8s( true, "header", ps, depth, sk->header, sizeof( sk->header )) )
    615                 return false;
    616         if ( !prs_uint16( "tag", ps, depth, &tag))
    617                 return false;
    618 
    619         if ( !prs_uint32( "prev_sk_off", ps, depth, &sk->prev_sk_off))
    620                 return false;
    621         if ( !prs_uint32( "next_sk_off", ps, depth, &sk->next_sk_off))
    622                 return false;
    623         if ( !prs_uint32( "ref_count", ps, depth, &sk->ref_count))
    624                 return false;
    625         if ( !prs_uint32( "size", ps, depth, &sk->size))
    626                 return false;
    627 
    628         if ( !sec_io_desc( "sec_desc", &sk->sec_desc, ps, depth ))
    629                 return false;
    630 
    631         end_off = hbin->ps.data_offset;
    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         if ( data_size > sk->rec_size )
    637                 DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, sk->rec_size));
    638 
    639         if ( !hbin->ps.io )
    640                 hbin->dirty = true;
    641 
    642         return true;
    643 }
    644 
    645 
    646 /*******************************************************************
    647 *******************************************************************/
     596  prs_struct *ps = &hbin->ps;
     597  uint16 tag = 0xFFFF;
     598  uint32 data_size, start_off, end_off;
     599
     600
     601  depth++;
     602
     603  if ( !prs_set_offset( &hbin->ps, sk->sk_off + HBIN_HDR_SIZE - hbin->first_hbin_off ) )
     604    return false;
     605
     606  /* backup and get the data_size */
     607       
     608  if ( !prs_set_offset( &hbin->ps, hbin->ps.data_offset-sizeof(uint32)) )
     609    return false;
     610  start_off = hbin->ps.data_offset;
     611  if ( !prs_uint32( "rec_size", &hbin->ps, depth, &sk->rec_size ))
     612    return false;
     613
     614  if ( !prs_uint8s( true, "header", ps, depth, sk->header, sizeof( sk->header )) )
     615    return false;
     616  if ( !prs_uint16( "tag", ps, depth, &tag))
     617    return false;
     618
     619  if ( !prs_uint32( "prev_sk_off", ps, depth, &sk->prev_sk_off))
     620    return false;
     621  if ( !prs_uint32( "next_sk_off", ps, depth, &sk->next_sk_off))
     622    return false;
     623  if ( !prs_uint32( "ref_count", ps, depth, &sk->ref_count))
     624    return false;
     625  if ( !prs_uint32( "size", ps, depth, &sk->size))
     626    return false;
     627
     628  if ( !sec_io_desc( "sec_desc", &sk->sec_desc, ps, depth ))
     629    return false;
     630
     631  end_off = hbin->ps.data_offset;
     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  if ( data_size > sk->rec_size )
     637    /*DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, sk->rec_size));*/
     638
     639    if ( !hbin->ps.io )
     640      hbin->dirty = true;
     641
     642  return true;
     643}
     644
     645
     646/*******************************************************************
     647 *******************************************************************/
    648648static bool hbin_prs_vk_rec( const char *desc, REGF_HBIN *hbin, int depth,
    649649                             REGF_VK_REC *vk, REGF_FILE *file )
    650650{
    651         uint32 offset;
    652         uint16 name_length;
    653         prs_struct *ps = &hbin->ps;
    654         uint32 data_size, start_off, end_off;
    655 
    656         depth++;
    657 
    658         /* backup and get the data_size */
    659        
    660         if ( !prs_set_offset( &hbin->ps, hbin->ps.data_offset-sizeof(uint32)) )
    661                 return false;
    662         start_off = hbin->ps.data_offset;
    663         if ( !prs_uint32( "rec_size", &hbin->ps, depth, &vk->rec_size ))
    664                 return false;
    665 
    666         if ( !prs_uint8s( true, "header", ps, depth, vk->header, sizeof( vk->header )) )
    667                 return false;
    668 
    669         if ( !hbin->ps.io )
    670                 name_length = strlen(vk->valuename);
    671 
    672         if ( !prs_uint16( "name_length", ps, depth, &name_length ))
    673                 return false;
    674         if ( !prs_uint32( "data_size", ps, depth, &vk->data_size ))
    675                 return false;
    676         if ( !prs_uint32( "data_off", ps, depth, &vk->data_off ))
    677                 return false;
    678         if ( !prs_uint32( "type", ps, depth, &vk->type))
    679                 return false;
    680         if ( !prs_uint16( "flag", ps, depth, &vk->flag))
    681                 return false;
    682 
    683         offset = ps->data_offset;
    684         offset += 2;    /* skip 2 bytes */
    685         prs_set_offset( ps, offset );
    686 
    687         /* get the name */
    688 
    689         if ( vk->flag&VK_FLAG_NAME_PRESENT ) {
    690 
    691                 if ( hbin->ps.io ) {
    692                   if ( !(vk->valuename = (char*)zcalloc(sizeof(char), name_length+1 )))
    693                                 return false;
    694                 }
    695                 if ( !prs_uint8s( true, "name", ps, depth, vk->valuename, name_length ) )
    696                         return false;
    697         }
    698 
    699         end_off = hbin->ps.data_offset;
    700 
    701         /* get the data if necessary */
    702 
    703         if ( vk->data_size != 0 ) {
    704                 bool charmode = false;
    705 
    706                 if ( (vk->type == REG_SZ) || (vk->type == REG_MULTI_SZ) )
    707                         charmode = true;
    708 
    709                 /* the data is stored in the offset if the size <= 4 */
    710 
    711                 if ( !(vk->data_size & VK_DATA_IN_OFFSET) ) {
    712                         REGF_HBIN *hblock = hbin;
    713                         uint32 data_rec_size;
    714 
    715                         if ( hbin->ps.io ) {
    716                           if ( !(vk->data = (uint8*)zcalloc(sizeof(uint8), vk->data_size) ) )
    717                                         return false;
    718                         }
    719 
    720                         /* this data can be in another hbin */
    721                         if ( !hbin_contains_offset( hbin, vk->data_off ) ) {
    722                                 if ( !(hblock = lookup_hbin_block( file, vk->data_off )) )
    723                                         return false;
    724                         }
    725                         if ( !(prs_set_offset( &hblock->ps, (vk->data_off+HBIN_HDR_SIZE-hblock->first_hbin_off)-sizeof(uint32) )) )
    726                                 return false;
    727 
    728                         if ( !hblock->ps.io ) {
    729                                 data_rec_size = ( (vk->data_size+sizeof(uint32)) & 0xfffffff8 ) + 8;
    730                                 data_rec_size = ( data_rec_size - 1 ) ^ 0xFFFFFFFF;
    731                         }
    732                         if ( !prs_uint32( "data_rec_size", &hblock->ps, depth, &data_rec_size ))
    733                                 return false;
    734                         if ( !prs_uint8s( charmode, "data", &hblock->ps, depth, vk->data, vk->data_size) )
    735                                 return false;
    736 
    737                         if ( !hblock->ps.io )
    738                                 hblock->dirty = true;
    739                 }
    740                 else {
    741                   if ( !(vk->data = zcalloc(sizeof(uint8), 4) ) )
    742                                 return false;
    743                         SIVAL( vk->data, 0, vk->data_off );
    744                 }
    745                
    746         }
    747 
    748         /* data_size must be divisible by 8 and large enough to hold the original record */
    749 
    750         data_size = ((start_off - end_off ) & 0xfffffff8 );
    751         if ( data_size !=  vk->rec_size )
    752                 DEBUG(10,("prs_vk_rec: data_size check failed (0x%x < 0x%x)\n", data_size, vk->rec_size));
    753 
    754         if ( !hbin->ps.io )
    755                 hbin->dirty = true;
    756 
    757         return true;
     651  uint32 offset;
     652  uint16 name_length;
     653  prs_struct *ps = &hbin->ps;
     654  uint32 data_size, start_off, end_off;
     655
     656  depth++;
     657
     658  /* backup and get the data_size */
     659       
     660  if ( !prs_set_offset( &hbin->ps, hbin->ps.data_offset-sizeof(uint32)) )
     661    return false;
     662  start_off = hbin->ps.data_offset;
     663  if ( !prs_uint32( "rec_size", &hbin->ps, depth, &vk->rec_size ))
     664    return false;
     665
     666  if ( !prs_uint8s( true, "header", ps, depth, vk->header, sizeof( vk->header )) )
     667    return false;
     668
     669  if ( !hbin->ps.io )
     670    name_length = strlen(vk->valuename);
     671
     672  if ( !prs_uint16( "name_length", ps, depth, &name_length ))
     673    return false;
     674  if ( !prs_uint32( "data_size", ps, depth, &vk->data_size ))
     675    return false;
     676  if ( !prs_uint32( "data_off", ps, depth, &vk->data_off ))
     677    return false;
     678  if ( !prs_uint32( "type", ps, depth, &vk->type))
     679    return false;
     680  if ( !prs_uint16( "flag", ps, depth, &vk->flag))
     681    return false;
     682
     683  offset = ps->data_offset;
     684  offset += 2;  /* skip 2 bytes */
     685  prs_set_offset( ps, offset );
     686
     687  /* get the name */
     688
     689  if ( vk->flag&VK_FLAG_NAME_PRESENT ) {
     690
     691    if ( hbin->ps.io ) {
     692      if ( !(vk->valuename = (char*)zcalloc(sizeof(char), name_length+1 )))
     693        return false;
     694    }
     695    if ( !prs_uint8s( true, "name", ps, depth, vk->valuename, name_length ) )
     696      return false;
     697  }
     698
     699  end_off = hbin->ps.data_offset;
     700
     701  /* get the data if necessary */
     702
     703  if ( vk->data_size != 0 ) {
     704    bool charmode = false;
     705
     706    if ( (vk->type == REG_SZ) || (vk->type == REG_MULTI_SZ) )
     707      charmode = true;
     708
     709    /* the data is stored in the offset if the size <= 4 */
     710
     711    if ( !(vk->data_size & VK_DATA_IN_OFFSET) ) {
     712      REGF_HBIN *hblock = hbin;
     713      uint32 data_rec_size;
     714
     715      if ( hbin->ps.io ) {
     716        if ( !(vk->data = (uint8*)zcalloc(sizeof(uint8), vk->data_size) ) )
     717          return false;
     718      }
     719
     720      /* this data can be in another hbin */
     721      if ( !hbin_contains_offset( hbin, vk->data_off ) ) {
     722        if ( !(hblock = lookup_hbin_block( file, vk->data_off )) )
     723          return false;
     724      }
     725      if ( !(prs_set_offset( &hblock->ps, (vk->data_off+HBIN_HDR_SIZE-hblock->first_hbin_off)-sizeof(uint32) )) )
     726        return false;
     727
     728      if ( !hblock->ps.io ) {
     729        data_rec_size = ( (vk->data_size+sizeof(uint32)) & 0xfffffff8 ) + 8;
     730        data_rec_size = ( data_rec_size - 1 ) ^ 0xFFFFFFFF;
     731      }
     732      if ( !prs_uint32( "data_rec_size", &hblock->ps, depth, &data_rec_size ))
     733        return false;
     734      if ( !prs_uint8s( charmode, "data", &hblock->ps, depth, vk->data, vk->data_size) )
     735        return false;
     736
     737      if ( !hblock->ps.io )
     738        hblock->dirty = true;
     739    }
     740    else {
     741      if ( !(vk->data = zcalloc(sizeof(uint8), 4) ) )
     742        return false;
     743      SIVAL( vk->data, 0, vk->data_off );
     744    }
     745               
     746  }
     747
     748  /* data_size must be divisible by 8 and large enough to hold the original record */
     749
     750  data_size = ((start_off - end_off ) & 0xfffffff8 );
     751  if ( data_size !=  vk->rec_size )
     752    /*DEBUG(10,("prs_vk_rec: data_size check failed (0x%x < 0x%x)\n", data_size, vk->rec_size));*/
     753
     754    if ( !hbin->ps.io )
     755      hbin->dirty = true;
     756
     757  return true;
    758758}
    759759
     
    766766                                 int depth, REGF_NK_REC *nk, REGF_FILE *file )
    767767{
    768         int i;
    769         uint32 record_size;
    770 
    771         depth++;
    772        
    773         /* check if we have anything to do first */
    774        
    775         if ( nk->num_values == 0 )
    776                 return true;
    777                
    778         if ( hbin->ps.io ) {
    779           if ( !(nk->values = (REGF_VK_REC*)zcalloc(sizeof(REGF_VK_REC), nk->num_values ) ) )
    780                         return false;
    781         }
    782        
    783         /* convert the offset to something relative to this HBIN block */
    784        
    785         if ( !prs_set_offset( &hbin->ps, nk->values_off+HBIN_HDR_SIZE-hbin->first_hbin_off-sizeof(uint32)) )
    786                 return false;
    787 
    788         if ( !hbin->ps.io ) {
    789                 record_size = ( ( nk->num_values * sizeof(uint32) ) & 0xfffffff8 ) + 8;
    790                 record_size = (record_size - 1) ^ 0xFFFFFFFF;
    791         }
    792 
    793         if ( !prs_uint32( "record_size", &hbin->ps, depth, &record_size ) )
    794                 return false;
    795                
    796         for ( i=0; i<nk->num_values; i++ ) {
    797                 if ( !prs_uint32( "vk_off", &hbin->ps, depth, &nk->values[i].rec_off ) )
    798                         return false;
    799         }
    800 
    801         for ( i=0; i<nk->num_values; i++ ) {
    802                 REGF_HBIN *sub_hbin = hbin;
    803                 uint32 new_offset;
    804        
    805                 if ( !hbin_contains_offset( hbin, nk->values[i].rec_off ) ) {
    806                         sub_hbin = lookup_hbin_block( file, nk->values[i].rec_off );
    807                         if ( !sub_hbin ) {
    808                                 DEBUG(0,("hbin_prs_vk_records: Failed to find HBIN block containing offset [0x%x]\n",
    809                                         nk->values[i].hbin_off));
    810                                 return false;
    811                         }
    812                 }
    813                
    814                 new_offset = nk->values[i].rec_off + HBIN_HDR_SIZE - sub_hbin->first_hbin_off;
    815                 if ( !prs_set_offset( &sub_hbin->ps, new_offset ) )
    816                         return false;
    817                 if ( !hbin_prs_vk_rec( "vk_rec", sub_hbin, depth, &nk->values[i], file ) )
    818                         return false;
    819         }
    820 
    821         if ( !hbin->ps.io )
    822                 hbin->dirty = true;
    823 
    824 
    825         return true;
    826 }
    827 
    828 
    829 /*******************************************************************
    830 *******************************************************************/
     768  int i;
     769  uint32 record_size;
     770
     771  depth++;
     772       
     773  /* check if we have anything to do first */
     774       
     775  if ( nk->num_values == 0 )
     776    return true;
     777               
     778  if ( hbin->ps.io ) {
     779    if ( !(nk->values = (REGF_VK_REC*)zcalloc(sizeof(REGF_VK_REC), nk->num_values ) ) )
     780      return false;
     781  }
     782       
     783  /* convert the offset to something relative to this HBIN block */
     784       
     785  if ( !prs_set_offset( &hbin->ps, nk->values_off+HBIN_HDR_SIZE-hbin->first_hbin_off-sizeof(uint32)) )
     786    return false;
     787
     788  if ( !hbin->ps.io ) {
     789    record_size = ( ( nk->num_values * sizeof(uint32) ) & 0xfffffff8 ) + 8;
     790    record_size = (record_size - 1) ^ 0xFFFFFFFF;
     791  }
     792
     793  if ( !prs_uint32( "record_size", &hbin->ps, depth, &record_size ) )
     794    return false;
     795               
     796  for ( i=0; i<nk->num_values; i++ ) {
     797    if ( !prs_uint32( "vk_off", &hbin->ps, depth, &nk->values[i].rec_off ) )
     798      return false;
     799  }
     800
     801  for ( i=0; i<nk->num_values; i++ ) {
     802    REGF_HBIN *sub_hbin = hbin;
     803    uint32 new_offset;
     804       
     805    if ( !hbin_contains_offset( hbin, nk->values[i].rec_off ) ) {
     806      sub_hbin = lookup_hbin_block( file, nk->values[i].rec_off );
     807      if ( !sub_hbin ) {
     808        /*DEBUG(0,("hbin_prs_vk_records: Failed to find HBIN block containing offset [0x%x]\n",
     809          nk->values[i].hbin_off));*/
     810        return false;
     811      }
     812    }
     813               
     814    new_offset = nk->values[i].rec_off + HBIN_HDR_SIZE - sub_hbin->first_hbin_off;
     815    if ( !prs_set_offset( &sub_hbin->ps, new_offset ) )
     816      return false;
     817    if ( !hbin_prs_vk_rec( "vk_rec", sub_hbin, depth, &nk->values[i], file ) )
     818      return false;
     819  }
     820
     821  if ( !hbin->ps.io )
     822    hbin->dirty = true;
     823
     824
     825  return true;
     826}
     827
     828
     829/*******************************************************************
     830 *******************************************************************/
    831831
    832832static REGF_SK_REC* find_sk_record_by_offset( REGF_FILE *file, uint32 offset )
    833833{
    834         REGF_SK_REC *p_sk;
    835        
    836         for ( p_sk=file->sec_desc_list; p_sk; p_sk=p_sk->next ) {
    837                 if ( p_sk->sk_off == offset )
    838                         return p_sk;
    839         }
    840        
    841         return NULL;
    842 }
    843 
    844 /*******************************************************************
    845 *******************************************************************/
     834  REGF_SK_REC *p_sk;
     835       
     836  for ( p_sk=file->sec_desc_list; p_sk; p_sk=p_sk->next ) {
     837    if ( p_sk->sk_off == offset )
     838      return p_sk;
     839  }
     840       
     841  return NULL;
     842}
     843
     844/*******************************************************************
     845 *******************************************************************/
    846846
    847847static REGF_SK_REC* find_sk_record_by_sec_desc( REGF_FILE *file, SEC_DESC *sd )
    848848{
    849         REGF_SK_REC *p;
    850 
    851         for ( p=file->sec_desc_list; p; p=p->next ) {
    852                 if ( sec_desc_equal( p->sec_desc, sd ) )
    853                         return p;
    854         }
    855 
    856         /* failure */
    857 
    858         return NULL;
    859 }
    860 
    861 /*******************************************************************
    862 *******************************************************************/
     849  REGF_SK_REC *p;
     850
     851  for ( p=file->sec_desc_list; p; p=p->next ) {
     852    if ( sec_desc_equal( p->sec_desc, sd ) )
     853      return p;
     854  }
     855
     856  /* failure */
     857
     858  return NULL;
     859}
     860
     861/*******************************************************************
     862 *******************************************************************/
    863863
    864864static bool hbin_prs_key( REGF_FILE *file, REGF_HBIN *hbin, REGF_NK_REC *nk )
    865865{
    866         int depth = 0;
    867         REGF_HBIN *sub_hbin;
    868        
    869         depth++;
    870 
    871         /* get the initial nk record */
    872        
    873         if ( !prs_nk_rec( "nk_rec", &hbin->ps, depth, nk ))
    874                 return false;
    875 
    876         /* fill in values */
    877        
    878         if ( nk->num_values && (nk->values_off!=REGF_OFFSET_NONE) ) {
    879                 sub_hbin = hbin;
    880                 if ( !hbin_contains_offset( hbin, nk->values_off ) ) {
    881                         sub_hbin = lookup_hbin_block( file, nk->values_off );
    882                         if ( !sub_hbin ) {
    883                                 DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing value_list_offset [0x%x]\n",
    884                                         nk->values_off));
    885                                 return false;
    886                         }
    887                 }
    888                
    889                 if ( !hbin_prs_vk_records( "vk_rec", sub_hbin, depth, nk, file ))
    890                         return false;
    891         }
    892                
    893         /* now get subkeys */
    894        
    895         if ( nk->num_subkeys && (nk->subkeys_off!=REGF_OFFSET_NONE) ) {
    896                 sub_hbin = hbin;
    897                 if ( !hbin_contains_offset( hbin, nk->subkeys_off ) ) {
    898                         sub_hbin = lookup_hbin_block( file, nk->subkeys_off );
    899                         if ( !sub_hbin ) {
    900                                 DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing subkey_offset [0x%x]\n",
    901                                         nk->subkeys_off));
    902                                 return false;
    903                         }
    904                 }
    905                
    906                 if ( !hbin_prs_lf_records( "lf_rec", sub_hbin, depth, nk ))
    907                         return false;
    908         }
    909 
    910         /* get the to the security descriptor.  First look if we have already parsed it */
    911        
    912         if ( (nk->sk_off!=REGF_OFFSET_NONE) && !( nk->sec_desc = find_sk_record_by_offset( file, nk->sk_off )) ) {
    913 
    914                 sub_hbin = hbin;
    915                 if ( !hbin_contains_offset( hbin, nk->sk_off ) ) {
    916                         sub_hbin = lookup_hbin_block( file, nk->sk_off );
    917                         if ( !sub_hbin ) {
    918                                 DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing sk_offset [0x%x]\n",
    919                                         nk->subkeys_off));
    920                                 return false;
    921                         }
    922                 }
    923                
    924                 if ( !(nk->sec_desc = (REGF_SK_REC*)zalloc(sizeof(REGF_SK_REC) )) )
    925                         return false;
    926                 nk->sec_desc->sk_off = nk->sk_off;
    927                 if ( !hbin_prs_sk_rec( "sk_rec", sub_hbin, depth, nk->sec_desc ))
    928                         return false;
     866  int depth = 0;
     867  REGF_HBIN *sub_hbin;
     868       
     869  depth++;
     870
     871  /* get the initial nk record */
     872       
     873  if ( !prs_nk_rec( "nk_rec", &hbin->ps, depth, nk ))
     874    return false;
     875
     876  /* fill in values */
     877       
     878  if ( nk->num_values && (nk->values_off!=REGF_OFFSET_NONE) ) {
     879    sub_hbin = hbin;
     880    if ( !hbin_contains_offset( hbin, nk->values_off ) ) {
     881      sub_hbin = lookup_hbin_block( file, nk->values_off );
     882      if ( !sub_hbin ) {
     883        /*DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing value_list_offset [0x%x]\n",
     884          nk->values_off));*/
     885        return false;
     886      }
     887    }
     888               
     889    if ( !hbin_prs_vk_records( "vk_rec", sub_hbin, depth, nk, file ))
     890      return false;
     891  }
     892               
     893  /* now get subkeys */
     894       
     895  if ( nk->num_subkeys && (nk->subkeys_off!=REGF_OFFSET_NONE) ) {
     896    sub_hbin = hbin;
     897    if ( !hbin_contains_offset( hbin, nk->subkeys_off ) ) {
     898      sub_hbin = lookup_hbin_block( file, nk->subkeys_off );
     899      if ( !sub_hbin ) {
     900        /*DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing subkey_offset [0x%x]\n",
     901          nk->subkeys_off));*/
     902        return false;
     903      }
     904    }
     905               
     906    if ( !hbin_prs_lf_records( "lf_rec", sub_hbin, depth, nk ))
     907      return false;
     908  }
     909
     910  /* get the to the security descriptor.  First look if we have already parsed it */
     911       
     912  if ( (nk->sk_off!=REGF_OFFSET_NONE) && !( nk->sec_desc = find_sk_record_by_offset( file, nk->sk_off )) ) {
     913
     914    sub_hbin = hbin;
     915    if ( !hbin_contains_offset( hbin, nk->sk_off ) ) {
     916      sub_hbin = lookup_hbin_block( file, nk->sk_off );
     917      if ( !sub_hbin ) {
     918        /*DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing sk_offset [0x%x]\n",
     919          nk->subkeys_off));*/
     920        return false;
     921      }
     922    }
     923               
     924    if ( !(nk->sec_desc = (REGF_SK_REC*)zalloc(sizeof(REGF_SK_REC) )) )
     925      return false;
     926    nk->sec_desc->sk_off = nk->sk_off;
     927    if ( !hbin_prs_sk_rec( "sk_rec", sub_hbin, depth, nk->sec_desc ))
     928      return false;
    929929                       
    930                 /* add to the list of security descriptors (ref_count has been read from the files) */
    931 
    932                 nk->sec_desc->sk_off = nk->sk_off;
    933                 DLIST_ADD( file->sec_desc_list, nk->sec_desc );
    934         }
    935                
    936         return true;
    937 }
    938 
    939 /*******************************************************************
    940 *******************************************************************/
     930    /* add to the list of security descriptors (ref_count has been read from the files) */
     931
     932    nk->sec_desc->sk_off = nk->sk_off;
     933    DLIST_ADD( file->sec_desc_list, nk->sec_desc );
     934  }
     935               
     936  return true;
     937}
     938
     939/*******************************************************************
     940 *******************************************************************/
    941941
    942942static bool next_record( REGF_HBIN *hbin, const char *hdr, bool *eob )
    943943{
    944         char header[REC_HDR_SIZE] = "";
    945         uint32 record_size;
    946         uint32 curr_off, block_size;
    947         bool found = false;
    948         prs_struct *ps = &hbin->ps;
    949        
    950         curr_off = ps->data_offset;
    951         if ( curr_off == 0 )
    952                 prs_set_offset( ps, HBIN_HEADER_REC_SIZE );
    953 
    954         /* assume that the current offset is at the reacord header
    955            and we need to backup to read the record size */
    956 
    957         curr_off -= sizeof(uint32);
    958 
    959         block_size = ps->buffer_size;
    960         record_size = 0;
    961         while ( !found ) {
    962 
    963                 curr_off = curr_off+record_size;
    964                 if ( curr_off >= block_size )
    965                         break;
    966 
    967                 if ( !prs_set_offset( &hbin->ps, curr_off) )
    968                         return false;
    969 
    970                 if ( !prs_uint32( "record_size", ps, 0, &record_size ) )
    971                         return false;
    972                 if ( !prs_uint8s( true, "header", ps, 0, header, REC_HDR_SIZE ) )
    973                         return false;
    974 
    975                 if ( record_size & 0x80000000 ) {
    976                         /* absolute_value(record_size) */
    977                         record_size = (record_size ^ 0xffffffff) + 1;
    978                 }
    979 
    980                 if ( memcmp( header, hdr, REC_HDR_SIZE ) == 0 ) {
    981                         found = true;
    982                         curr_off += sizeof(uint32);
    983                 }
    984         }
    985 
    986         /* mark prs_struct as done ( at end ) if no more SK records */
    987         /* mark end-of-block as true */
    988        
    989         if ( !found )
    990         {
    991           prs_set_offset( &hbin->ps, hbin->ps.buffer_size );
    992           *eob = true;
    993           return false;
    994         }
    995                
    996         if ( !prs_set_offset( ps, curr_off ) )
    997                 return false;
    998 
    999         return true;
    1000 }
    1001 
    1002 
    1003 /*******************************************************************
    1004 *******************************************************************/
     944  char header[REC_HDR_SIZE] = "";
     945  uint32 record_size;
     946  uint32 curr_off, block_size;
     947  bool found = false;
     948  prs_struct *ps = &hbin->ps;
     949       
     950  curr_off = ps->data_offset;
     951  if ( curr_off == 0 )
     952    prs_set_offset( ps, HBIN_HEADER_REC_SIZE );
     953
     954  /* assume that the current offset is at the reacord header
     955     and we need to backup to read the record size */
     956
     957  curr_off -= sizeof(uint32);
     958
     959  block_size = ps->buffer_size;
     960  record_size = 0;
     961  while ( !found ) {
     962
     963    curr_off = curr_off+record_size;
     964    if ( curr_off >= block_size )
     965      break;
     966
     967    if ( !prs_set_offset( &hbin->ps, curr_off) )
     968      return false;
     969
     970    if ( !prs_uint32( "record_size", ps, 0, &record_size ) )
     971      return false;
     972    if ( !prs_uint8s( true, "header", ps, 0, header, REC_HDR_SIZE ) )
     973      return false;
     974
     975    if ( record_size & 0x80000000 ) {
     976      /* absolute_value(record_size) */
     977      record_size = (record_size ^ 0xffffffff) + 1;
     978    }
     979
     980    if ( memcmp( header, hdr, REC_HDR_SIZE ) == 0 ) {
     981      found = true;
     982      curr_off += sizeof(uint32);
     983    }
     984  }
     985
     986  /* mark prs_struct as done ( at end ) if no more SK records */
     987  /* mark end-of-block as true */
     988       
     989  if ( !found )
     990  {
     991    prs_set_offset( &hbin->ps, hbin->ps.buffer_size );
     992    *eob = true;
     993    return false;
     994  }
     995               
     996  if ( !prs_set_offset( ps, curr_off ) )
     997    return false;
     998
     999  return true;
     1000}
     1001
     1002
     1003/*******************************************************************
     1004 *******************************************************************/
    10051005static bool next_nk_record( REGF_FILE *file, REGF_HBIN *hbin, REGF_NK_REC *nk, bool *eob )
    10061006{
    1007         if ( next_record( hbin, "nk", eob ) && hbin_prs_key( file, hbin, nk ) )
    1008                 return true;
    1009        
    1010         return false;
    1011 }
    1012 
    1013 
    1014 /*******************************************************************
    1015  Intialize the newly created REGF_BLOCK in *file and write the
    1016  block header to disk
    1017 *******************************************************************/
    1018 static bool init_regf_block( REGF_FILE *file )
    1019 {       
    1020         prs_struct ps;
    1021         bool result = true;
    1022        
    1023         if ( !prs_init( &ps, REGF_BLOCKSIZE, file->mem_ctx, MARSHALL ) )
    1024                 return false;
    1025                
    1026         memcpy( file->header, "regf", REGF_HDR_SIZE );
    1027         file->data_offset = 0x20;
    1028         file->last_block  = 0x1000;
    1029        
    1030         /* set mod time */
    1031        
    1032         unix_to_nt_time( &file->mtime, time(NULL) );
    1033        
    1034         /* hard coded values...no diea what these are ... maybe in time */
    1035        
    1036         file->unknown1 = 0x2;
    1037         file->unknown2 = 0x1;
    1038         file->unknown3 = 0x3;
    1039         file->unknown4 = 0x0;
    1040         file->unknown5 = 0x1;
    1041         file->unknown6 = 0x1;
    1042        
    1043         /* write header to the buffer */
    1044        
    1045         if ( !prs_regf_block( "regf_header", &ps, 0, file ) ) {
    1046                 result = false;
    1047                 goto out;
    1048         }
    1049        
    1050         /* calculate the checksum, re-marshall data (to include the checksum)
    1051            and write to disk */
    1052        
    1053         file->checksum = regf_block_checksum( &ps );
    1054         prs_set_offset( &ps, 0 );
    1055         if ( !prs_regf_block( "regf_header", &ps, 0, file ) ) {
    1056                 result = false;
    1057                 goto out;
    1058         }
    1059                
    1060 out:
    1061         if(ps.is_dynamic)
    1062           SAFE_FREE(ps.data_p);
    1063         ps.is_dynamic = false;
    1064         ps.buffer_size = 0;
    1065         ps.data_offset = 0;
    1066 
    1067         return result;
     1007  if ( next_record( hbin, "nk", eob ) && hbin_prs_key( file, hbin, nk ) )
     1008    return true;
     1009       
     1010  return false;
    10681011}
    10691012
     
    10751018REGF_FILE* regfio_open( const char *filename )
    10761019{
    1077         REGF_FILE *rb;
    1078         int flags = O_RDONLY;
    1079 
    1080         if ( !(rb = (REGF_FILE*)malloc(sizeof(REGF_FILE))) ) {
    1081                 DEBUG(0,("ERROR allocating memory\n"));
    1082                 return NULL;
    1083         }
    1084         zerop( rb );
    1085         rb->fd = -1;
    1086        
    1087         /*      if ( !(rb->mem_ctx = talloc_init( "read_regf_block" )) )
    1088         {
    1089           regfio_close( rb );
    1090           return NULL;
    1091         }
    1092         */
    1093         rb->open_flags = flags;
    1094        
    1095         /* open and existing file */
    1096 
    1097         if ( (rb->fd = open(filename, flags)) == -1 ) {
    1098                 DEBUG(0,("regfio_open: failure to open %s (%s)\n", filename, strerror(errno)));
    1099                 regfio_close( rb );
    1100                 return NULL;
    1101         }
    1102        
    1103         /* check if we are creating a new file or overwriting an existing one */
    1104                
    1105         if ( flags & (O_CREAT|O_TRUNC) ) {
    1106                 if ( !init_regf_block( rb ) ) {
    1107                         DEBUG(0,("regfio_open: Failed to read initial REGF block\n"));
    1108                         regfio_close( rb );
    1109                         return NULL;
    1110                 }
    1111                
    1112                 /* success */
    1113                 return rb;
    1114         }
    1115        
    1116         /* read in an existing file */
    1117        
    1118         if ( !read_regf_block( rb ) ) {
    1119                 DEBUG(0,("regfio_open: Failed to read initial REGF block\n"));
    1120                 regfio_close( rb );
    1121                 return NULL;
    1122         }
    1123        
    1124         /* success */
    1125        
    1126         return rb;
    1127 }
    1128 
    1129 
    1130 /*******************************************************************
    1131 *******************************************************************/
     1020  REGF_FILE *rb;
     1021  int flags = O_RDONLY;
     1022
     1023  if ( !(rb = (REGF_FILE*)malloc(sizeof(REGF_FILE))) ) {
     1024    /* DEBUG(0,("ERROR allocating memory\n")); */
     1025    return NULL;
     1026  }
     1027  memset(rb, 0, sizeof(REGF_FILE));
     1028  rb->fd = -1;
     1029       
     1030  /*    if ( !(rb->mem_ctx = talloc_init( "read_regf_block" )) )
     1031    {
     1032    regfio_close( rb );
     1033    return NULL;
     1034    }
     1035  */
     1036  rb->open_flags = flags;
     1037       
     1038  /* open and existing file */
     1039
     1040  if ( (rb->fd = open(filename, flags)) == -1 ) {
     1041    /* DEBUG(0,("regfio_open: failure to open %s (%s)\n", filename, strerror(errno)));*/
     1042    regfio_close( rb );
     1043    return NULL;
     1044  }
     1045       
     1046  /* read in an existing file */
     1047       
     1048  if ( !read_regf_block( rb ) ) {
     1049    /* DEBUG(0,("regfio_open: Failed to read initial REGF block\n"));*/
     1050    regfio_close( rb );
     1051    return NULL;
     1052  }
     1053       
     1054  /* success */
     1055       
     1056  return rb;
     1057}
     1058
     1059
     1060/*******************************************************************
     1061 *******************************************************************/
    11321062static void regfio_mem_free( REGF_FILE *file )
    11331063{
    1134         /* free any zalloc()'d memory */
     1064  /* free any zalloc()'d memory */
    11351065       
    11361066  /*    if ( file && file->mem_ctx )
    1137                 free(file->mem_ctx);
     1067    free(file->mem_ctx);
    11381068  */
    11391069}
     
    11411071
    11421072/*******************************************************************
    1143 *******************************************************************/
     1073 *******************************************************************/
    11441074int regfio_close( REGF_FILE *file )
    11451075{
    1146         int fd;
    1147 
    1148         regfio_mem_free( file );
    1149 
    1150         /* nothing to do if there is no open file */
    1151 
    1152         if ( !file || (file->fd == -1) )
    1153                 return 0;
    1154                
    1155         fd = file->fd;
    1156         file->fd = -1;
    1157         SAFE_FREE( file );
    1158 
    1159         return close( fd );
     1076  int fd;
     1077
     1078  regfio_mem_free( file );
     1079
     1080  /* nothing to do if there is no open file */
     1081
     1082  if ( !file || (file->fd == -1) )
     1083    return 0;
     1084               
     1085  fd = file->fd;
     1086  file->fd = -1;
     1087  SAFE_FREE( file );
     1088
     1089  return close( fd );
    11601090}
    11611091
     
    11671097REGF_NK_REC* regfio_rootkey( REGF_FILE *file )
    11681098{
    1169         REGF_NK_REC *nk;
    1170         REGF_HBIN   *hbin;
    1171         uint32      offset = REGF_BLOCKSIZE;
    1172         bool        found = false;
    1173         bool        eob;
    1174        
    1175         if ( !file )
    1176                 return NULL;
    1177                
    1178         if ( !(nk = (REGF_NK_REC*)zalloc(sizeof(REGF_NK_REC) )) ) {
    1179                 DEBUG(0,("regfio_rootkey: zalloc() failed!\n"));
    1180                 return NULL;
     1099  REGF_NK_REC *nk;
     1100  REGF_HBIN   *hbin;
     1101  uint32      offset = REGF_BLOCKSIZE;
     1102  bool        found = false;
     1103  bool        eob;
     1104       
     1105  if ( !file )
     1106    return NULL;
     1107               
     1108  if ( !(nk = (REGF_NK_REC*)zalloc(sizeof(REGF_NK_REC) )) ) {
     1109    /*DEBUG(0,("regfio_rootkey: zalloc() failed!\n"));*/
     1110    return NULL;
     1111  }
     1112       
     1113  /* scan through the file on HBIN block at a time looking
     1114     for an NK record with a type == 0x002c.
     1115     Normally this is the first nk record in the first hbin
     1116     block (but I'm not assuming that for now) */
     1117       
     1118  while ( (hbin = read_hbin_block( file, offset )) ) {
     1119    eob = false;
     1120
     1121    while ( !eob) {
     1122      if ( next_nk_record( file, hbin, nk, &eob ) ) {
     1123        if ( nk->key_type == NK_TYPE_ROOTKEY ) {
     1124          found = true;
     1125          break;
    11811126        }
    1182        
    1183         /* scan through the file on HBIN block at a time looking
    1184            for an NK record with a type == 0x002c.
    1185            Normally this is the first nk record in the first hbin
    1186            block (but I'm not assuming that for now) */
    1187        
    1188         while ( (hbin = read_hbin_block( file, offset )) ) {
    1189                 eob = false;
    1190 
    1191                 while ( !eob) {
    1192                         if ( next_nk_record( file, hbin, nk, &eob ) ) {
    1193                                 if ( nk->key_type == NK_TYPE_ROOTKEY ) {
    1194                                         found = true;
    1195                                         break;
    1196                                 }
    1197                         }
    1198                         if(hbin->ps.is_dynamic)
    1199                           SAFE_FREE(hbin->ps.data_p);
    1200                         hbin->ps.is_dynamic = false;
    1201                         hbin->ps.buffer_size = 0;
    1202                         hbin->ps.data_offset = 0;
    1203                 }
    1204                
    1205                 if ( found )
    1206                         break;
    1207 
    1208                 offset += hbin->block_size;
    1209         }
    1210        
    1211         if ( !found ) {
    1212                 DEBUG(0,("regfio_rootkey: corrupt registry file ?  No root key record located\n"));
    1213                 return NULL;
    1214         }
    1215 
    1216         DLIST_ADD( file->block_list, hbin );
    1217 
    1218         return nk;             
     1127      }
     1128      if(hbin->ps.is_dynamic)
     1129        SAFE_FREE(hbin->ps.data_p);
     1130      hbin->ps.is_dynamic = false;
     1131      hbin->ps.buffer_size = 0;
     1132      hbin->ps.data_offset = 0;
     1133    }
     1134               
     1135    if ( found )
     1136      break;
     1137
     1138    offset += hbin->block_size;
     1139  }
     1140       
     1141  if ( !found ) {
     1142    /*DEBUG(0,("regfio_rootkey: corrupt registry file ?  No root key record located\n"));*/
     1143    return NULL;
     1144  }
     1145
     1146  DLIST_ADD( file->block_list, hbin );
     1147
     1148  return nk;           
    12191149}
    12201150
     
    12261156REGF_NK_REC* regfio_fetch_subkey( REGF_FILE *file, REGF_NK_REC *nk )
    12271157{
    1228         REGF_NK_REC *subkey;
    1229         REGF_HBIN   *hbin;
    1230         uint32      nk_offset;
    1231 
    1232         /* see if there is anything left to report */
    1233        
    1234         if ( !nk || (nk->subkeys_off==REGF_OFFSET_NONE) || (nk->subkey_index >= nk->num_subkeys) )
    1235                 return NULL;
    1236 
    1237         /* find the HBIN block which should contain the nk record */
    1238        
    1239         if ( !(hbin = lookup_hbin_block( file, nk->subkeys.hashes[nk->subkey_index].nk_off )) ) {
    1240                 DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing offset [0x%x]\n",
    1241                         nk->subkeys.hashes[nk->subkey_index].nk_off));
    1242                 return NULL;
    1243         }
    1244        
    1245         nk_offset = nk->subkeys.hashes[nk->subkey_index].nk_off;
    1246         if ( !prs_set_offset( &hbin->ps, (HBIN_HDR_SIZE + nk_offset - hbin->first_hbin_off) ) )
    1247                 return NULL;
    1248                
    1249         nk->subkey_index++;
    1250         if (!(subkey = (REGF_NK_REC*)zalloc(sizeof(REGF_NK_REC))))
    1251                 return NULL;
    1252 
    1253         if ( !hbin_prs_key( file, hbin, subkey ) )
    1254                 return NULL;
    1255        
    1256         return subkey;
    1257 }
     1158  REGF_NK_REC *subkey;
     1159  REGF_HBIN   *hbin;
     1160  uint32      nk_offset;
     1161
     1162  /* see if there is anything left to report */
     1163       
     1164  if ( !nk || (nk->subkeys_off==REGF_OFFSET_NONE) || (nk->subkey_index >= nk->num_subkeys) )
     1165    return NULL;
     1166
     1167  /* find the HBIN block which should contain the nk record */
     1168       
     1169  if(!(hbin
     1170       = lookup_hbin_block(file, nk->subkeys.hashes[nk->subkey_index].nk_off )))
     1171  {
     1172    /*DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing offset [0x%x]\n",
     1173      nk->subkeys.hashes[nk->subkey_index].nk_off));*/
     1174    return NULL;
     1175  }
     1176       
     1177  nk_offset = nk->subkeys.hashes[nk->subkey_index].nk_off;
     1178  if ( !prs_set_offset( &hbin->ps, (HBIN_HDR_SIZE + nk_offset - hbin->first_hbin_off) ) )
     1179    return NULL;
     1180               
     1181  nk->subkey_index++;
     1182  if (!(subkey = (REGF_NK_REC*)zalloc(sizeof(REGF_NK_REC))))
     1183    return NULL;
     1184
     1185  if ( !hbin_prs_key( file, hbin, subkey ) )
     1186    return NULL;
     1187       
     1188  return subkey;
     1189}
Note: See TracChangeset for help on using the changeset viewer.