source: trunk/lib/regfio.c @ 59

Last change on this file since 59 was 59, checked in by tim, 19 years ago

Updated version

Code format cleanup, some comments added.

  • Property svn:keywords set to Id
File size: 37.2 KB
RevLine 
[30]1/*
2 * Branched from Samba project Subversion repository, version #7470:
3 *   http://websvn.samba.org/cgi-bin/viewcvs.cgi/trunk/source/registry/regfio.c
4 *
5 * Unix SMB/CIFS implementation.
6 * Windows NT registry I/O library
7 *
8 * Copyright (C) 2005 Timothy D. Morgan
9 * Copyright (C) 2005 Gerald (Jerry) Carter
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2 of the License.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
23 *
24 * $Id: regfio.c 59 2005-10-03 01:26:12Z tim $
25 */
26
27#include "../include/regfio.h"
28
29
30
[32]31/* Registry types mapping */
32const VAL_STR reg_type_names[] = 
33{
34  { REG_SZ,                        "SZ"           },
35  { REG_EXPAND_SZ,                 "EXPAND_SZ"    },
[41]36  { REG_BINARY,                    "BINARY"       },
[32]37  { REG_DWORD,                     "DWORD"        },
38  { REG_DWORD_BE,                  "DWORD_BE"     },
39  { REG_LINK,                      "LINK"         },
40  { REG_MULTI_SZ,                  "MULTI_SZ"     },
41  { REG_RESOURCE_LIST,             "RSRC_LIST"    },
42  { REG_FULL_RESOURCE_DESCRIPTOR,  "RSRC_DESC"    },
43  { REG_RESOURCE_REQUIREMENTS_LIST,"RSRC_REQ_LIST"},
44  { REG_KEY,                       "KEY"          },
45  { 0,                             NULL           },
46};
[30]47
[32]48
49/* Returns NULL on error */
[41]50const char* regfio_type_val2str(unsigned int val)
[32]51{
52  int i;
53
54  for(i=0; reg_type_names[i].val && reg_type_names[i].str; i++)
55    if (reg_type_names[i].val == val) 
56      return reg_type_names[i].str;
57
58  return NULL;
59}
60
61
62/* Returns 0 on error */
[41]63int regfio_type_str2val(const char* str)
[32]64{
65  int i;
66
67  for(i=0; reg_type_names[i].val && reg_type_names[i].str; i++) 
68    if (strcmp(reg_type_names[i].str, str) == 0) 
69      return reg_type_names[i].val;
70
71  return 0;
72}
73
74
[53]75/* Security descriptor parsing functions  */
76
77const char* regfio_ace_type2str(uint8 type)
78{
79  static const char* map[7] 
80    = {"ALLOW", "DENY", "AUDIT", "ALARM", 
81       "ALLOW CPD", "OBJ ALLOW", "OBJ DENY"};
82  if(type < 7)
83    return map[type];
84  else
85    /* XXX: would be nice to return the unknown integer value. 
86     *      However, as it is a const string, it can't be free()ed later on,
87     *      so that would need to change.
88     */
89    return "UNKNOWN";
90}
91
92
93/* XXX: this could probably be more efficient */
94char* regfio_ace_flags2str(uint8 flags)
95{
96  char* flg_output = malloc(21*sizeof(char));
97  int some = 0;
98
99  if(flg_output == NULL)
100    return NULL;
101
102  flg_output[0] = '\0';
103  if (!flags)
104    return flg_output;
105
106  if (flags & 0x01) {
107    if (some) strcat(flg_output, " ");
108    some = 1;
109    strcat(flg_output, "OI");
110  }
111  if (flags & 0x02) {
112    if (some) strcat(flg_output, " ");
113    some = 1;
114    strcat(flg_output, "CI");
115  }
116  if (flags & 0x04) {
117    if (some) strcat(flg_output, " ");
118    some = 1;
119    strcat(flg_output, "NP");
120  }
121  if (flags & 0x08) {
122    if (some) strcat(flg_output, " ");
123    some = 1;
124    strcat(flg_output, "IO");
125  }
126  if (flags & 0x10) {
127    if (some) strcat(flg_output, " ");
128    some = 1;
129    strcat(flg_output, "IA");
130  }
[59]131  /* XXX: Is this check right?  0xF == 1|2|4|8, which makes it redundant... */
[53]132  if (flags == 0xF) {
133    if (some) strcat(flg_output, " ");
134    some = 1;
135    strcat(flg_output, "VI");
136  }
137
138  return flg_output;
139}
140
141
142char* regfio_ace_perms2str(uint32 perms)
143{
144  char* ret_val = malloc(9*sizeof(char));
145  if(ret_val == NULL)
146    return NULL;
147
148  /* XXX: this should probably be parsed better */
149  sprintf(ret_val, "%.8X", perms);
150
151  return ret_val;
152}
153
154
155char* regfio_sid2str(DOM_SID* sid)
156{
157  uint32 i, size = MAXSUBAUTHS*11 + 24;
158  uint32 left = size;
159  uint8 comps = sid->num_auths;
160  char* ret_val = malloc(size);
161 
162  if(ret_val == NULL)
163    return NULL;
164
165  if(comps > MAXSUBAUTHS)
166    comps = MAXSUBAUTHS;
167
168  left -= sprintf(ret_val, "S-%u-%u", sid->sid_rev_num, sid->id_auth[5]);
169
170  for (i = 0; i < comps; i++) 
171    left -= snprintf(ret_val+(size-left), left, "-%u", sid->sub_auths[i]);
172
173  return ret_val;
174}
175
176
177char* regfio_get_acl(SEC_ACL* acl)
178{
179  uint32 i, extra, size = 0;
180  const char* type_str;
181  char* flags_str;
182  char* perms_str;
183  char* sid_str;
184  char* ret_val = NULL;
185  char* ace_delim = "";
186  char field_delim = ':';
187
188  for (i = 0; i < acl->num_aces; i++)
189  {
190    sid_str = regfio_sid2str(&acl->ace[i].trustee);
191    type_str = regfio_ace_type2str(acl->ace[i].type);
192    perms_str = regfio_ace_perms2str(acl->ace[i].info.mask);
193    flags_str = regfio_ace_flags2str(acl->ace[i].flags);
194   
195    if(flags_str == NULL || perms_str == NULL 
196       || type_str == NULL || sid_str == NULL)
197      return NULL;
198
199    /* XXX: this is slow */
200    extra = strlen(sid_str) + strlen(type_str) 
201          + strlen(perms_str) + strlen(flags_str)+5;
202    ret_val = realloc(ret_val, size+extra);
203    if(ret_val == NULL)
204      return NULL;
205    size += snprintf(ret_val+size, extra, "%s%s%c%s%c%s%c%s",
206                     ace_delim,sid_str,
207                     field_delim,type_str,
208                     field_delim,perms_str,
209                     field_delim,flags_str);
210    ace_delim = "|";
211    free(sid_str);
212    free(perms_str);
213    free(flags_str);
214  }
215
216  return ret_val;
217}
218
219
220char* regfio_get_sacl(SEC_DESC *sec_desc)
221{
222  if (sec_desc->sacl)
223    return regfio_get_acl(sec_desc->sacl);
224  else
225    return NULL;
226}
227
228
229char* regfio_get_dacl(SEC_DESC *sec_desc)
230{
231  if (sec_desc->dacl)
232    return regfio_get_acl(sec_desc->dacl);
233  else
234    return NULL;
235}
236
237
238char* regfio_get_owner(SEC_DESC *sec_desc)
239{
240  return regfio_sid2str(sec_desc->owner_sid);
241}
242
243
244char* regfio_get_group(SEC_DESC *sec_desc)
245{
246  return regfio_sid2str(sec_desc->grp_sid);
247}
248
249
250
[30]251/*******************************************************************
[31]252 *******************************************************************/
[30]253static int read_block( REGF_FILE *file, prs_struct *ps, uint32 file_offset, 
254                       uint32 block_size )
255{
[31]256  int bytes_read, returned;
257  char *buffer;
258  SMB_STRUCT_STAT sbuf;
[30]259
[31]260  /* check for end of file */
[30]261
[31]262  if ( fstat( file->fd, &sbuf ) ) {
263    /*DEBUG(0,("read_block: stat() failed! (%s)\n", strerror(errno)));*/
264    return -1;
265  }
[30]266
[31]267  if ( (size_t)file_offset >= sbuf.st_size )
268    return -1;
[30]269       
[31]270  /* if block_size == 0, we are parsnig HBIN records and need
271     to read some of the header to get the block_size from there */
[30]272           
[31]273  if ( block_size == 0 ) {
274    uint8 hdr[0x20];
[30]275
[31]276    if ( lseek( file->fd, file_offset, SEEK_SET ) == -1 ) {
277      /*DEBUG(0,("read_block: lseek() failed! (%s)\n", strerror(errno) ));*/
278      return -1;
279    }
[30]280
[31]281    returned = read( file->fd, hdr, 0x20 );
282    if ( (returned == -1) || (returned < 0x20) ) {
283      /*DEBUG(0,("read_block: failed to read in HBIN header. Is the file corrupt?\n"));*/
284      return -1;
285    }
[30]286
[31]287    /* make sure this is an hbin header */
[30]288
[53]289    if ( strncmp( (char*)hdr, "hbin", HBIN_HDR_SIZE ) != 0 ) {
[31]290      /*DEBUG(0,("read_block: invalid block header!\n"));*/
291      return -1;
292    }
[30]293
[31]294    block_size = IVAL( hdr, 0x08 );
295  }
[30]296
[31]297  /*DEBUG(10,("read_block: block_size == 0x%x\n", block_size ));*/
[30]298
[31]299  /* set the offset, initialize the buffer, and read the block from disk */
[30]300
[31]301  if ( lseek( file->fd, file_offset, SEEK_SET ) == -1 ) {
302    /*DEBUG(0,("read_block: lseek() failed! (%s)\n", strerror(errno) ));*/
303    return -1;
304  }
[30]305       
[31]306  prs_init( ps, block_size, file->mem_ctx, UNMARSHALL );
307  buffer = ps->data_p;
308  bytes_read = returned = 0;
[30]309
[32]310  while ( bytes_read < block_size ) 
311  {
312    if((returned = 
313        read(file->fd, buffer+bytes_read, block_size-bytes_read)) == -1)
314    {
[31]315      /*DEBUG(0,("read_block: read() failed (%s)\n", strerror(errno) ));*/
316      return false;
317    }
[32]318    if ((returned == 0) && (bytes_read < block_size)) 
319    {
[31]320      /*DEBUG(0,("read_block: not a vald registry file ?\n" ));*/
321      return false;
322    }   
[32]323
[31]324    bytes_read += returned;
325  }
[30]326       
[31]327  return bytes_read;
[30]328}
329
330
331/*******************************************************************
[31]332 *******************************************************************/
[53]333static bool prs_regf_block(const char *desc, prs_struct *ps, 
334                           int depth, REGF_FILE *file)
[30]335{
[31]336  depth++;
[30]337       
[53]338  if(!prs_uint8s(true, "header", ps, depth, file->header, sizeof(file->header)))
[31]339    return false;
[30]340       
[31]341  /* yes, these values are always identical so store them only once */
[30]342       
[31]343  if ( !prs_uint32( "unknown1", ps, depth, &file->unknown1 ))
344    return false;
345  if ( !prs_uint32( "unknown1 (again)", ps, depth, &file->unknown1 ))
346    return false;
[30]347
[31]348  /* get the modtime */
[30]349       
[31]350  if ( !prs_set_offset( ps, 0x0c ) )
351    return false;
352  if ( !smb_io_time( "modtime", &file->mtime, ps, depth ) )
353    return false;
[30]354
[31]355  /* constants */
[30]356       
[31]357  if ( !prs_uint32( "unknown2", ps, depth, &file->unknown2 ))
358    return false;
359  if ( !prs_uint32( "unknown3", ps, depth, &file->unknown3 ))
360    return false;
361  if ( !prs_uint32( "unknown4", ps, depth, &file->unknown4 ))
362    return false;
363  if ( !prs_uint32( "unknown5", ps, depth, &file->unknown5 ))
364    return false;
[30]365
[31]366  /* get file offsets */
[30]367       
[31]368  if ( !prs_set_offset( ps, 0x24 ) )
369    return false;
370  if ( !prs_uint32( "data_offset", ps, depth, &file->data_offset ))
371    return false;
372  if ( !prs_uint32( "last_block", ps, depth, &file->last_block ))
373    return false;
[30]374               
[31]375  /* one more constant */
[30]376       
[31]377  if ( !prs_uint32( "unknown6", ps, depth, &file->unknown6 ))
378    return false;
[30]379               
[31]380  /* get the checksum */
[30]381       
[31]382  if ( !prs_set_offset( ps, 0x01fc ) )
383    return false;
384  if ( !prs_uint32( "checksum", ps, depth, &file->checksum ))
385    return false;
[30]386       
[31]387  return true;
[30]388}
389
390
391/*******************************************************************
[31]392 *******************************************************************/
[53]393static bool prs_hbin_block(const char *desc, prs_struct *ps, 
394                           int depth, REGF_HBIN *hbin)
[30]395{
[31]396  uint32 block_size2;
[30]397
[31]398  depth++;
[30]399       
[53]400  if(!prs_uint8s(true, "header", ps, depth, hbin->header, sizeof(hbin->header)))
[31]401    return false;
[30]402
[31]403  if ( !prs_uint32( "first_hbin_off", ps, depth, &hbin->first_hbin_off ))
404    return false;
[30]405
[31]406  /* The dosreg.cpp comments say that the block size is at 0x1c.
407     According to a WINXP NTUSER.dat file, this is wrong.  The block_size
408     is at 0x08 */
[30]409
[31]410  if ( !prs_uint32( "block_size", ps, depth, &hbin->block_size ))
411    return false;
[30]412
[31]413  block_size2 = hbin->block_size;
414  prs_set_offset( ps, 0x1c );
415  if ( !prs_uint32( "block_size2", ps, depth, &block_size2 ))
416    return false;
[30]417
[31]418  if ( !ps->io )
419    hbin->dirty = true;
[30]420       
421
[31]422  return true;
[30]423}
424
425
426/*******************************************************************
[31]427 *******************************************************************/
[33]428static bool prs_nk_rec( const char *desc, prs_struct *ps, 
429                        int depth, REGF_NK_REC *nk )
[30]430{
[31]431  uint16 class_length, name_length;
432  uint32 start;
433  uint32 data_size, start_off, end_off;
434  uint32 unknown_off = REGF_OFFSET_NONE;
[30]435
[31]436  nk->hbin_off = ps->data_offset;
437  start = nk->hbin_off;
[30]438       
[31]439  depth++;
[30]440       
[33]441  /* back up and get the data_size */   
[31]442  if ( !prs_set_offset( ps, ps->data_offset-sizeof(uint32)) )
443    return false;
444  start_off = ps->data_offset;
445  if ( !prs_uint32( "rec_size", ps, depth, &nk->rec_size ))
446    return false;
[30]447       
[33]448  if (!prs_uint8s(true, "header", ps, depth, nk->header, sizeof(nk->header)))
[31]449    return false;
[30]450               
[31]451  if ( !prs_uint16( "key_type", ps, depth, &nk->key_type ))
452    return false;
453  if ( !smb_io_time( "mtime", &nk->mtime, ps, depth ))
454    return false;
[30]455               
[31]456  if ( !prs_set_offset( ps, start+0x0010 ) )
457    return false;
458  if ( !prs_uint32( "parent_off", ps, depth, &nk->parent_off ))
459    return false;
460  if ( !prs_uint32( "num_subkeys", ps, depth, &nk->num_subkeys ))
461    return false;
[30]462               
[31]463  if ( !prs_set_offset( ps, start+0x001c ) )
464    return false;
465  if ( !prs_uint32( "subkeys_off", ps, depth, &nk->subkeys_off ))
466    return false;
467  if ( !prs_uint32( "unknown_off", ps, depth, &unknown_off) )
468    return false;
[30]469               
[31]470  if ( !prs_set_offset( ps, start+0x0024 ) )
471    return false;
472  if ( !prs_uint32( "num_values", ps, depth, &nk->num_values ))
473    return false;
474  if ( !prs_uint32( "values_off", ps, depth, &nk->values_off ))
475    return false;
476  if ( !prs_uint32( "sk_off", ps, depth, &nk->sk_off ))
477    return false;
478  if ( !prs_uint32( "classname_off", ps, depth, &nk->classname_off ))
479    return false;
[30]480
[33]481  if (!prs_uint32("max_bytes_subkeyname", ps, depth, &nk->max_bytes_subkeyname))
[31]482    return false;
[33]483  if ( !prs_uint32( "max_bytes_subkeyclassname", ps, 
484                    depth, &nk->max_bytes_subkeyclassname))
485  { return false; }
[31]486  if ( !prs_uint32( "max_bytes_valuename", ps, depth, &nk->max_bytes_valuename))
487    return false;
488  if ( !prs_uint32( "max_bytes_value", ps, depth, &nk->max_bytes_value))
489    return false;
490  if ( !prs_uint32( "unknown index", ps, depth, &nk->unk_index))
491    return false;
[30]492
[31]493  name_length = nk->keyname ? strlen(nk->keyname) : 0 ;
494  class_length = nk->classname ? strlen(nk->classname) : 0 ;
495  if ( !prs_uint16( "name_length", ps, depth, &name_length ))
496    return false;
497  if ( !prs_uint16( "class_length", ps, depth, &class_length ))
498    return false;       
[30]499               
[33]500  if ( class_length ) 
501  {
[31]502    ;;
503  }
[30]504       
[33]505  if ( name_length ) 
506  {
507    if(ps->io && !(nk->keyname = (char*)zcalloc(sizeof(char), name_length+1)))
[31]508        return false;
[30]509
[53]510    if(!prs_uint8s(true, "name", ps, depth, (uint8*)nk->keyname, name_length))
[31]511      return false;
[30]512
[53]513    if(ps->io)
[31]514      nk->keyname[name_length] = '\0';
515  }
[30]516
[31]517  end_off = ps->data_offset;
[30]518
[33]519  /* data_size must be divisible by 8 and large enough to hold
520     the original record */
[30]521
[31]522  data_size = ((start_off - end_off) & 0xfffffff8 );
[33]523  /*if ( data_size > nk->rec_size )
524      DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, nk->rec_size));*/
[30]525
[33]526  if ( !ps->io )
527    nk->hbin->dirty = true;
528 
529  nk->subkey_index = 0;
[31]530  return true;
[30]531}
532
533
534/*******************************************************************
[31]535 *******************************************************************/
[30]536static uint32 regf_block_checksum( prs_struct *ps )
537{
[31]538  char *buffer = ps->data_p;
539  uint32 checksum, x;
540  int i;
[30]541
[31]542  /* XOR of all bytes 0x0000 - 0x01FB */
[30]543               
[31]544  checksum = x = 0;
[30]545       
[31]546  for ( i=0; i<0x01FB; i+=4 ) {
547    x = IVAL(buffer, i );
548    checksum ^= x;
549  }
[30]550       
[31]551  return checksum;
[30]552}
553
554
555/*******************************************************************
[31]556 *******************************************************************/
[30]557static bool read_regf_block( REGF_FILE *file )
558{
[31]559  prs_struct ps;
560  uint32 checksum;
[30]561       
[31]562  /* grab the first block from the file */
[30]563               
[31]564  if ( read_block( file, &ps, 0, REGF_BLOCKSIZE ) == -1 )
565    return false;
[30]566       
[31]567  /* parse the block and verify the checksum */
[30]568       
[31]569  if ( !prs_regf_block( "regf_header", &ps, 0, file ) )
570    return false;       
[30]571               
[31]572  checksum = regf_block_checksum( &ps );
[30]573       
[31]574  if(ps.is_dynamic)
575    SAFE_FREE(ps.data_p);
576  ps.is_dynamic = false;
577  ps.buffer_size = 0;
578  ps.data_offset = 0;
[30]579
[31]580  if ( file->checksum !=  checksum ) {
581    /*DEBUG(0,("read_regf_block: invalid checksum\n" ));*/
582    return false;
583  }
[30]584
[31]585  return true;
[30]586}
587
588
589/*******************************************************************
[31]590 *******************************************************************/
[30]591static REGF_HBIN* read_hbin_block( REGF_FILE *file, off_t offset )
592{
[31]593  REGF_HBIN *hbin;
594  uint32 record_size, curr_off, block_size, header;
[30]595       
[31]596  if ( !(hbin = (REGF_HBIN*)zalloc(sizeof(REGF_HBIN))) ) 
597    return NULL;
598  hbin->file_off = offset;
599  hbin->free_off = -1;
[30]600               
[31]601  if ( read_block( file, &hbin->ps, offset, 0 ) == -1 )
602    return NULL;
[30]603       
[31]604  if ( !prs_hbin_block( "hbin", &hbin->ps, 0, hbin ) )
605    return NULL;       
[30]606
[31]607  /* this should be the same thing as hbin->block_size but just in case */
[30]608
[31]609  block_size = hbin->ps.buffer_size;
[30]610
[31]611  /* Find the available free space offset.  Always at the end,
612     so walk the record list and stop when you get to the end.
613     The end is defined by a record header of 0xffffffff.  The
614     previous 4 bytes contains the amount of free space remaining
615     in the hbin block. */
[30]616
[31]617  /* remember that the record_size is in the 4 bytes preceeding the record itself */
[30]618
[31]619  if ( !prs_set_offset( &hbin->ps, file->data_offset+HBIN_HDR_SIZE-sizeof(uint32) ) )
620    return false;
[30]621
[31]622  record_size = 0;
623  curr_off = hbin->ps.data_offset;
624  while ( header != 0xffffffff ) {
625    /* not done yet so reset the current offset to the
626       next record_size field */
[30]627
[31]628    curr_off = curr_off+record_size;
[30]629
[31]630    /* for some reason the record_size of the last record in
631       an hbin block can extend past the end of the block
632       even though the record fits within the remaining
633       space....aaarrrgggghhhhhh */
[30]634
[31]635    if ( curr_off >= block_size ) {
636      record_size = -1;
637      curr_off = -1;
638      break;
639    }
[30]640
[31]641    if ( !prs_set_offset( &hbin->ps, curr_off) )
642      return false;
[30]643
[31]644    if ( !prs_uint32( "rec_size", &hbin->ps, 0, &record_size ) )
645      return false;
646    if ( !prs_uint32( "header", &hbin->ps, 0, &header ) )
647      return false;
[30]648               
[31]649    assert( record_size != 0 );
[30]650
[31]651    if ( record_size & 0x80000000 ) {
652      /* absolute_value(record_size) */
653      record_size = (record_size ^ 0xffffffff) + 1;
654    }
655  }
[30]656
[31]657  /* save the free space offset */
[30]658
[31]659  if ( header == 0xffffffff ) {
[30]660
[31]661    /* account for the fact that the curr_off is 4 bytes behind the actual
662       record header */
[30]663
[31]664    hbin->free_off = curr_off + sizeof(uint32);
665    hbin->free_size = record_size;
666  }
[30]667
[31]668  /*DEBUG(10,("read_hbin_block: free space offset == 0x%x\n", hbin->free_off));*/
[30]669
[31]670  if ( !prs_set_offset( &hbin->ps, file->data_offset+HBIN_HDR_SIZE )  )
671    return false;
[30]672       
[31]673  return hbin;
[30]674}
675
676
677/*******************************************************************
678 Input a randon offset and receive the correpsonding HBIN
679 block for it
680*******************************************************************/
681static bool hbin_contains_offset( REGF_HBIN *hbin, uint32 offset )
682{
[31]683  if ( !hbin )
684    return false;
[30]685       
[31]686  if ( (offset > hbin->first_hbin_off) && (offset < (hbin->first_hbin_off+hbin->block_size)) )
687    return true;
[30]688               
[31]689  return false;
[30]690}
691
692
693/*******************************************************************
694 Input a randon offset and receive the correpsonding HBIN
695 block for it
696*******************************************************************/
697static REGF_HBIN* lookup_hbin_block( REGF_FILE *file, uint32 offset )
698{
[31]699  REGF_HBIN *hbin = NULL;
700  uint32 block_off;
[30]701
[31]702  /* start with the open list */
[30]703
[31]704  for ( hbin=file->block_list; hbin; hbin=hbin->next ) {
705    /* DEBUG(10,("lookup_hbin_block: address = 0x%x [0x%x]\n", hbin->file_off, (uint32)hbin ));*/
706    if ( hbin_contains_offset( hbin, offset ) )
707      return hbin;
708  }
[30]709       
[31]710  if ( !hbin ) {
711    /* start at the beginning */
[30]712
[31]713    block_off = REGF_BLOCKSIZE;
714    do {
715      /* cleanup before the next round */
716      if ( hbin )
717      {
718        if(hbin->ps.is_dynamic)
719          SAFE_FREE(hbin->ps.data_p);
720        hbin->ps.is_dynamic = false;
721        hbin->ps.buffer_size = 0;
722        hbin->ps.data_offset = 0;
723      }
[30]724
[31]725      hbin = read_hbin_block( file, block_off );
[30]726
[31]727      if ( hbin ) 
728        block_off = hbin->file_off + hbin->block_size;
[30]729
[31]730    } while ( hbin && !hbin_contains_offset( hbin, offset ) );
731  }
[30]732
[31]733  if ( hbin )
734    DLIST_ADD( file->block_list, hbin );
[30]735
[31]736  return hbin;
[30]737}
738
739
740/*******************************************************************
[31]741 *******************************************************************/
[30]742static bool prs_hash_rec( const char *desc, prs_struct *ps, int depth, REGF_HASH_REC *hash )
743{
[31]744  depth++;
[30]745
[31]746  if ( !prs_uint32( "nk_off", ps, depth, &hash->nk_off ))
747    return false;
748  if ( !prs_uint8s( true, "keycheck", ps, depth, hash->keycheck, sizeof( hash->keycheck )) )
749    return false;
[30]750       
[31]751  return true;
[30]752}
753
754
755/*******************************************************************
[31]756 *******************************************************************/
[53]757static bool hbin_prs_lf_records(const char *desc, REGF_HBIN *hbin, 
758                                int depth, REGF_NK_REC *nk)
[30]759{
[31]760  int i;
761  REGF_LF_REC *lf = &nk->subkeys;
762  uint32 data_size, start_off, end_off;
[30]763
[31]764  depth++;
[30]765
[31]766  /* check if we have anything to do first */
[30]767       
[31]768  if ( nk->num_subkeys == 0 )
769    return true;
[30]770
[31]771  /* move to the LF record */
[30]772
[31]773  if ( !prs_set_offset( &hbin->ps, nk->subkeys_off + HBIN_HDR_SIZE - hbin->first_hbin_off ) )
774    return false;
[30]775
[31]776  /* backup and get the data_size */
[30]777       
[31]778  if ( !prs_set_offset( &hbin->ps, hbin->ps.data_offset-sizeof(uint32)) )
779    return false;
780  start_off = hbin->ps.data_offset;
781  if ( !prs_uint32( "rec_size", &hbin->ps, depth, &lf->rec_size ))
782    return false;
[30]783
[53]784  if(!prs_uint8s(true, "header", &hbin->ps, depth, 
785                 lf->header, sizeof(lf->header)))
[31]786    return false;
[30]787               
[31]788  if ( !prs_uint16( "num_keys", &hbin->ps, depth, &lf->num_keys))
789    return false;
[30]790
[31]791  if ( hbin->ps.io ) {
792    if ( !(lf->hashes = (REGF_HASH_REC*)zcalloc(sizeof(REGF_HASH_REC), lf->num_keys )) )
793      return false;
794  }
[30]795
[31]796  for ( i=0; i<lf->num_keys; i++ ) {
797    if ( !prs_hash_rec( "hash_rec", &hbin->ps, depth, &lf->hashes[i] ) )
798      return false;
799  }
[30]800
[31]801  end_off = hbin->ps.data_offset;
[30]802
[31]803  /* data_size must be divisible by 8 and large enough to hold the original record */
[30]804
[31]805  data_size = ((start_off - end_off) & 0xfffffff8 );
[33]806  /*  if ( data_size > lf->rec_size )*/
[31]807    /*DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, lf->rec_size));*/
[30]808
[33]809  if ( !hbin->ps.io )
810    hbin->dirty = true;
[30]811
[31]812  return true;
[30]813}
814
815
816/*******************************************************************
[31]817 *******************************************************************/
[30]818static bool hbin_prs_sk_rec( const char *desc, REGF_HBIN *hbin, int depth, REGF_SK_REC *sk )
819{
[31]820  prs_struct *ps = &hbin->ps;
821  uint16 tag = 0xFFFF;
822  uint32 data_size, start_off, end_off;
[30]823
824
[31]825  depth++;
[30]826
[31]827  if ( !prs_set_offset( &hbin->ps, sk->sk_off + HBIN_HDR_SIZE - hbin->first_hbin_off ) )
828    return false;
[30]829
[31]830  /* backup and get the data_size */
[30]831       
[31]832  if ( !prs_set_offset( &hbin->ps, hbin->ps.data_offset-sizeof(uint32)) )
833    return false;
834  start_off = hbin->ps.data_offset;
835  if ( !prs_uint32( "rec_size", &hbin->ps, depth, &sk->rec_size ))
836    return false;
[30]837
[53]838  if (!prs_uint8s(true, "header", ps, depth, sk->header, sizeof(sk->header)))
[31]839    return false;
840  if ( !prs_uint16( "tag", ps, depth, &tag))
841    return false;
[30]842
[31]843  if ( !prs_uint32( "prev_sk_off", ps, depth, &sk->prev_sk_off))
844    return false;
845  if ( !prs_uint32( "next_sk_off", ps, depth, &sk->next_sk_off))
846    return false;
847  if ( !prs_uint32( "ref_count", ps, depth, &sk->ref_count))
848    return false;
849  if ( !prs_uint32( "size", ps, depth, &sk->size))
850    return false;
[30]851
[31]852  if ( !sec_io_desc( "sec_desc", &sk->sec_desc, ps, depth )) 
853    return false;
[30]854
[31]855  end_off = hbin->ps.data_offset;
[30]856
[31]857  /* data_size must be divisible by 8 and large enough to hold the original record */
[30]858
[31]859  data_size = ((start_off - end_off) & 0xfffffff8 );
[33]860  /*  if ( data_size > sk->rec_size )*/
[31]861    /*DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, sk->rec_size));*/
[30]862
[33]863  if ( !hbin->ps.io )
864    hbin->dirty = true;
[30]865
[31]866  return true;
[30]867}
868
869
870/*******************************************************************
[31]871 *******************************************************************/
[30]872static bool hbin_prs_vk_rec( const char *desc, REGF_HBIN *hbin, int depth, 
873                             REGF_VK_REC *vk, REGF_FILE *file )
874{
[31]875  uint32 offset;
876  uint16 name_length;
877  prs_struct *ps = &hbin->ps;
878  uint32 data_size, start_off, end_off;
[30]879
[31]880  depth++;
[30]881
[31]882  /* backup and get the data_size */
[30]883       
[31]884  if ( !prs_set_offset( &hbin->ps, hbin->ps.data_offset-sizeof(uint32)) )
885    return false;
886  start_off = hbin->ps.data_offset;
887  if ( !prs_uint32( "rec_size", &hbin->ps, depth, &vk->rec_size ))
888    return false;
[30]889
[31]890  if ( !prs_uint8s( true, "header", ps, depth, vk->header, sizeof( vk->header )) )
891    return false;
[30]892
[31]893  if ( !hbin->ps.io )
894    name_length = strlen(vk->valuename);
[30]895
[31]896  if ( !prs_uint16( "name_length", ps, depth, &name_length ))
897    return false;
898  if ( !prs_uint32( "data_size", ps, depth, &vk->data_size ))
899    return false;
900  if ( !prs_uint32( "data_off", ps, depth, &vk->data_off ))
901    return false;
902  if ( !prs_uint32( "type", ps, depth, &vk->type))
903    return false;
904  if ( !prs_uint16( "flag", ps, depth, &vk->flag))
905    return false;
[30]906
[31]907  offset = ps->data_offset;
908  offset += 2;  /* skip 2 bytes */
909  prs_set_offset( ps, offset );
[30]910
[31]911  /* get the name */
[30]912
[31]913  if ( vk->flag&VK_FLAG_NAME_PRESENT ) {
[30]914
[31]915    if ( hbin->ps.io ) {
916      if ( !(vk->valuename = (char*)zcalloc(sizeof(char), name_length+1 )))
917        return false;
918    }
[53]919    if ( !prs_uint8s(true, "name", ps, depth, 
920                     (uint8*)vk->valuename, name_length) )
[31]921      return false;
922  }
[30]923
[31]924  end_off = hbin->ps.data_offset;
[30]925
[31]926  /* get the data if necessary */
[30]927
[32]928  if ( vk->data_size != 0 ) 
929  {
[31]930    bool charmode = false;
[30]931
[31]932    if ( (vk->type == REG_SZ) || (vk->type == REG_MULTI_SZ) )
933      charmode = true;
[30]934
[31]935    /* the data is stored in the offset if the size <= 4 */
[32]936    if ( !(vk->data_size & VK_DATA_IN_OFFSET) ) 
937    {
[31]938      REGF_HBIN *hblock = hbin;
939      uint32 data_rec_size;
[30]940
[32]941      if ( hbin->ps.io ) 
942      {
[31]943        if ( !(vk->data = (uint8*)zcalloc(sizeof(uint8), vk->data_size) ) )
944          return false;
945      }
[30]946
[31]947      /* this data can be in another hbin */
[32]948      if ( !hbin_contains_offset( hbin, vk->data_off ) ) 
949      {
[31]950        if ( !(hblock = lookup_hbin_block( file, vk->data_off )) )
951          return false;
952      }
[32]953      if (!(prs_set_offset(&hblock->ps, 
954                           (vk->data_off
955                            + HBIN_HDR_SIZE
956                            - hblock->first_hbin_off)
957                           - sizeof(uint32))))
958      { return false; }
[30]959
[32]960      if ( !hblock->ps.io ) 
961      {
[31]962        data_rec_size = ( (vk->data_size+sizeof(uint32)) & 0xfffffff8 ) + 8;
963        data_rec_size = ( data_rec_size - 1 ) ^ 0xFFFFFFFF;
964      }
965      if ( !prs_uint32( "data_rec_size", &hblock->ps, depth, &data_rec_size ))
966        return false;
[32]967      if(!prs_uint8s(charmode, "data", &hblock->ps, depth, 
968                     vk->data, vk->data_size))
[31]969        return false;
[30]970
[31]971      if ( !hblock->ps.io )
972        hblock->dirty = true;
973    }
[32]974    else 
975    {
976      if(!(vk->data = zcalloc(sizeof(uint8), 4)))
[31]977        return false;
978      SIVAL( vk->data, 0, vk->data_off );
979    }
[30]980               
[31]981  }
[30]982
[31]983  /* data_size must be divisible by 8 and large enough to hold the original record */
[30]984
[31]985  data_size = ((start_off - end_off ) & 0xfffffff8 );
[32]986  /*if ( data_size !=  vk->rec_size )
987    DEBUG(10,("prs_vk_rec: data_size check failed (0x%x < 0x%x)\n", data_size, vk->rec_size));*/
[30]988
[32]989  if ( !hbin->ps.io )
990    hbin->dirty = true;
[30]991
[31]992  return true;
[30]993}
994
995
996/*******************************************************************
997 read a VK record which is contained in the HBIN block stored
998 in the prs_struct *ps.
999*******************************************************************/
[32]1000static bool hbin_prs_vk_records(const char *desc, REGF_HBIN *hbin, 
1001                                int depth, REGF_NK_REC *nk, REGF_FILE *file)
[30]1002{
[31]1003  int i;
1004  uint32 record_size;
[30]1005
[31]1006  depth++;
[30]1007       
[31]1008  /* check if we have anything to do first */
[32]1009  if(nk->num_values == 0)
[31]1010    return true;
[30]1011               
[32]1012  if(hbin->ps.io)
1013  {
1014    if (!(nk->values = (REGF_VK_REC*)zcalloc(sizeof(REGF_VK_REC), 
1015                                              nk->num_values )))
[31]1016      return false;
1017  }
[30]1018       
[31]1019  /* convert the offset to something relative to this HBIN block */
[32]1020  if (!prs_set_offset(&hbin->ps, 
1021                      nk->values_off
1022                      + HBIN_HDR_SIZE
1023                      - hbin->first_hbin_off
1024                      - sizeof(uint32)))
1025  { return false; }
[30]1026
[32]1027  if ( !hbin->ps.io ) 
1028  { 
[31]1029    record_size = ( ( nk->num_values * sizeof(uint32) ) & 0xfffffff8 ) + 8;
1030    record_size = (record_size - 1) ^ 0xFFFFFFFF;
1031  }
[30]1032
[31]1033  if ( !prs_uint32( "record_size", &hbin->ps, depth, &record_size ) )
1034    return false;
[30]1035               
[32]1036  for ( i=0; i<nk->num_values; i++ ) 
1037  {
[31]1038    if ( !prs_uint32( "vk_off", &hbin->ps, depth, &nk->values[i].rec_off ) )
1039      return false;
1040  }
[30]1041
[32]1042  for ( i=0; i<nk->num_values; i++ ) 
1043  {
[31]1044    REGF_HBIN *sub_hbin = hbin;
1045    uint32 new_offset;
[30]1046       
[32]1047    if ( !hbin_contains_offset( hbin, nk->values[i].rec_off ) ) 
1048    {
[31]1049      sub_hbin = lookup_hbin_block( file, nk->values[i].rec_off );
[32]1050      if ( !sub_hbin ) 
1051      {
[31]1052        /*DEBUG(0,("hbin_prs_vk_records: Failed to find HBIN block containing offset [0x%x]\n",
1053          nk->values[i].hbin_off));*/
1054        return false;
1055      }
1056    }
[30]1057               
[32]1058    new_offset = nk->values[i].rec_off
1059      + HBIN_HDR_SIZE
1060      - sub_hbin->first_hbin_off;
1061
1062    if (!prs_set_offset(&sub_hbin->ps, new_offset))
[31]1063      return false;
[32]1064    if (!hbin_prs_vk_rec("vk_rec", sub_hbin, depth, &nk->values[i], file))
[31]1065      return false;
1066  }
[30]1067
[31]1068  if ( !hbin->ps.io )
1069    hbin->dirty = true;
[30]1070
[31]1071  return true;
[30]1072}
1073
1074
1075/*******************************************************************
[31]1076 *******************************************************************/
[30]1077static REGF_SK_REC* find_sk_record_by_offset( REGF_FILE *file, uint32 offset )
1078{
[31]1079  REGF_SK_REC *p_sk;
[30]1080       
[31]1081  for ( p_sk=file->sec_desc_list; p_sk; p_sk=p_sk->next ) {
1082    if ( p_sk->sk_off == offset ) 
1083      return p_sk;
1084  }
[30]1085       
[31]1086  return NULL;
[30]1087}
1088
[32]1089
[30]1090/*******************************************************************
[31]1091 *******************************************************************/
[30]1092static REGF_SK_REC* find_sk_record_by_sec_desc( REGF_FILE *file, SEC_DESC *sd )
1093{
[31]1094  REGF_SK_REC *p;
[30]1095
[31]1096  for ( p=file->sec_desc_list; p; p=p->next ) {
1097    if ( sec_desc_equal( p->sec_desc, sd ) )
1098      return p;
1099  }
[30]1100
[31]1101  /* failure */
[30]1102
[31]1103  return NULL;
[30]1104}
1105
[32]1106
[30]1107/*******************************************************************
[31]1108 *******************************************************************/
[30]1109static bool hbin_prs_key( REGF_FILE *file, REGF_HBIN *hbin, REGF_NK_REC *nk )
1110{
[31]1111  int depth = 0;
1112  REGF_HBIN *sub_hbin;
[30]1113       
[31]1114  depth++;
[30]1115
[31]1116  /* get the initial nk record */
[33]1117  if (!prs_nk_rec("nk_rec", &hbin->ps, depth, nk))
[31]1118    return false;
[30]1119
[31]1120  /* fill in values */
[32]1121  if ( nk->num_values && (nk->values_off!=REGF_OFFSET_NONE) ) 
1122  {
[31]1123    sub_hbin = hbin;
[32]1124    if ( !hbin_contains_offset( hbin, nk->values_off ) ) 
1125    {
[31]1126      sub_hbin = lookup_hbin_block( file, nk->values_off );
[32]1127      if ( !sub_hbin ) 
1128      {
[31]1129        /*DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing value_list_offset [0x%x]\n",
1130          nk->values_off));*/
1131        return false;
1132      }
1133    }
[30]1134               
[32]1135    if(!hbin_prs_vk_records("vk_rec", sub_hbin, depth, nk, file))
[31]1136      return false;
1137  }
[30]1138               
[31]1139  /* now get subkeys */
[32]1140  if ( nk->num_subkeys && (nk->subkeys_off!=REGF_OFFSET_NONE) ) 
1141  {
[31]1142    sub_hbin = hbin;
[32]1143    if ( !hbin_contains_offset( hbin, nk->subkeys_off ) ) 
1144    {
[31]1145      sub_hbin = lookup_hbin_block( file, nk->subkeys_off );
[32]1146      if ( !sub_hbin ) 
1147      {
[31]1148        /*DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing subkey_offset [0x%x]\n",
1149          nk->subkeys_off));*/
1150        return false;
1151      }
1152    }
[30]1153               
[32]1154    if (!hbin_prs_lf_records("lf_rec", sub_hbin, depth, nk))
[31]1155      return false;
1156  }
[30]1157
[31]1158  /* get the to the security descriptor.  First look if we have already parsed it */
[30]1159       
[32]1160  if ((nk->sk_off!=REGF_OFFSET_NONE) 
1161      && !(nk->sec_desc = find_sk_record_by_offset( file, nk->sk_off )))
1162  {
[31]1163    sub_hbin = hbin;
[32]1164    if (!hbin_contains_offset(hbin, nk->sk_off))
1165    {
[31]1166      sub_hbin = lookup_hbin_block( file, nk->sk_off );
1167      if ( !sub_hbin ) {
1168        /*DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing sk_offset [0x%x]\n",
1169          nk->subkeys_off));*/
1170        return false;
1171      }
1172    }
[30]1173               
[31]1174    if ( !(nk->sec_desc = (REGF_SK_REC*)zalloc(sizeof(REGF_SK_REC) )) )
1175      return false;
1176    nk->sec_desc->sk_off = nk->sk_off;
1177    if ( !hbin_prs_sk_rec( "sk_rec", sub_hbin, depth, nk->sec_desc ))
1178      return false;
[30]1179                       
[31]1180    /* add to the list of security descriptors (ref_count has been read from the files) */
[30]1181
[31]1182    nk->sec_desc->sk_off = nk->sk_off;
1183    DLIST_ADD( file->sec_desc_list, nk->sec_desc );
1184  }
[30]1185               
[31]1186  return true;
[30]1187}
1188
[32]1189
[30]1190/*******************************************************************
[31]1191 *******************************************************************/
[30]1192static bool next_record( REGF_HBIN *hbin, const char *hdr, bool *eob )
1193{
[53]1194  uint8 header[REC_HDR_SIZE] = "";
[31]1195  uint32 record_size;
1196  uint32 curr_off, block_size;
1197  bool found = false;
1198  prs_struct *ps = &hbin->ps;
[30]1199       
[31]1200  curr_off = ps->data_offset;
1201  if ( curr_off == 0 )
1202    prs_set_offset( ps, HBIN_HEADER_REC_SIZE );
[30]1203
[31]1204  /* assume that the current offset is at the reacord header
1205     and we need to backup to read the record size */
1206  curr_off -= sizeof(uint32);
[30]1207
[31]1208  block_size = ps->buffer_size;
1209  record_size = 0;
[32]1210  while ( !found ) 
1211  {
[31]1212    curr_off = curr_off+record_size;
1213    if ( curr_off >= block_size ) 
1214      break;
[30]1215
[31]1216    if ( !prs_set_offset( &hbin->ps, curr_off) )
1217      return false;
[30]1218
[31]1219    if ( !prs_uint32( "record_size", ps, 0, &record_size ) )
1220      return false;
1221    if ( !prs_uint8s( true, "header", ps, 0, header, REC_HDR_SIZE ) )
1222      return false;
[30]1223
[31]1224    if ( record_size & 0x80000000 ) {
1225      /* absolute_value(record_size) */
1226      record_size = (record_size ^ 0xffffffff) + 1;
1227    }
[30]1228
[31]1229    if ( memcmp( header, hdr, REC_HDR_SIZE ) == 0 ) {
1230      found = true;
1231      curr_off += sizeof(uint32);
1232    }
1233  } 
[30]1234
[31]1235  /* mark prs_struct as done ( at end ) if no more SK records */
[32]1236  /* mark end-of-block as true */       
1237  if ( !found )
[31]1238  {
1239    prs_set_offset( &hbin->ps, hbin->ps.buffer_size );
1240    *eob = true;
1241    return false;
1242  }
[32]1243
1244  if (!prs_set_offset(ps, curr_off))
[31]1245    return false;
[30]1246
[31]1247  return true;
[30]1248}
1249
1250
1251/*******************************************************************
[31]1252 *******************************************************************/
[32]1253static bool next_nk_record(REGF_FILE *file, REGF_HBIN *hbin, 
1254                           REGF_NK_REC *nk, bool *eob)
[30]1255{
[32]1256  if (next_record(hbin, "nk", eob) 
1257      && hbin_prs_key(file, hbin, nk))
[31]1258    return true;
[30]1259       
[31]1260  return false;
[30]1261}
1262
1263
1264/*******************************************************************
1265 Open the registry file and then read in the REGF block to get the
1266 first hbin offset.
1267*******************************************************************/
1268REGF_FILE* regfio_open( const char *filename )
1269{
[31]1270  REGF_FILE *rb;
1271  int flags = O_RDONLY;
[30]1272
[31]1273  if ( !(rb = (REGF_FILE*)malloc(sizeof(REGF_FILE))) ) {
1274    /* DEBUG(0,("ERROR allocating memory\n")); */
1275    return NULL;
1276  }
1277  memset(rb, 0, sizeof(REGF_FILE));
1278  rb->fd = -1;
[30]1279       
[31]1280  /*    if ( !(rb->mem_ctx = talloc_init( "read_regf_block" )) )
1281    {
1282    regfio_close( rb );
1283    return NULL;
1284    }
1285  */
1286  rb->open_flags = flags;
[30]1287       
[31]1288  /* open and existing file */
[30]1289
[31]1290  if ( (rb->fd = open(filename, flags)) == -1 ) {
1291    /* DEBUG(0,("regfio_open: failure to open %s (%s)\n", filename, strerror(errno)));*/
1292    regfio_close( rb );
1293    return NULL;
1294  }
[30]1295       
[31]1296  /* read in an existing file */
[30]1297       
[31]1298  if ( !read_regf_block( rb ) ) {
1299    /* DEBUG(0,("regfio_open: Failed to read initial REGF block\n"));*/
1300    regfio_close( rb );
1301    return NULL;
1302  }
[30]1303       
[31]1304  /* success */
[30]1305       
[31]1306  return rb;
[30]1307}
1308
1309
1310/*******************************************************************
[31]1311 *******************************************************************/
[30]1312static void regfio_mem_free( REGF_FILE *file )
1313{
[31]1314  /* free any zalloc()'d memory */
[30]1315       
1316  /*    if ( file && file->mem_ctx )
[31]1317    free(file->mem_ctx);
[30]1318  */
1319}
1320
1321
1322/*******************************************************************
[31]1323 *******************************************************************/
[30]1324int regfio_close( REGF_FILE *file )
1325{
[31]1326  int fd;
[30]1327
[31]1328  regfio_mem_free( file );
[30]1329
[31]1330  /* nothing to do if there is no open file */
[30]1331
[31]1332  if ( !file || (file->fd == -1) )
1333    return 0;
[30]1334               
[31]1335  fd = file->fd;
1336  file->fd = -1;
1337  SAFE_FREE( file );
[30]1338
[31]1339  return close( fd );
[30]1340}
1341
1342
1343/*******************************************************************
1344 There should be only *one* root key in the registry file based
1345 on my experience.  --jerry
1346*******************************************************************/
1347REGF_NK_REC* regfio_rootkey( REGF_FILE *file )
1348{
[31]1349  REGF_NK_REC *nk;
1350  REGF_HBIN   *hbin;
1351  uint32      offset = REGF_BLOCKSIZE;
1352  bool        found = false;
1353  bool        eob;
[30]1354       
[31]1355  if ( !file )
1356    return NULL;
[30]1357               
[31]1358  if ( !(nk = (REGF_NK_REC*)zalloc(sizeof(REGF_NK_REC) )) ) {
1359    /*DEBUG(0,("regfio_rootkey: zalloc() failed!\n"));*/
1360    return NULL;
1361  }
[30]1362       
[31]1363  /* scan through the file on HBIN block at a time looking
1364     for an NK record with a type == 0x002c.
1365     Normally this is the first nk record in the first hbin
1366     block (but I'm not assuming that for now) */
[30]1367       
[31]1368  while ( (hbin = read_hbin_block( file, offset )) ) {
1369    eob = false;
[30]1370
[31]1371    while ( !eob) {
1372      if ( next_nk_record( file, hbin, nk, &eob ) ) {
1373        if ( nk->key_type == NK_TYPE_ROOTKEY ) {
1374          found = true;
1375          break;
1376        }
1377      }
1378      if(hbin->ps.is_dynamic)
1379        SAFE_FREE(hbin->ps.data_p);
1380      hbin->ps.is_dynamic = false;
1381      hbin->ps.buffer_size = 0;
1382      hbin->ps.data_offset = 0;
1383    }
[30]1384               
[31]1385    if ( found ) 
1386      break;
[30]1387
[31]1388    offset += hbin->block_size;
1389  }
[30]1390       
[31]1391  if ( !found ) {
1392    /*DEBUG(0,("regfio_rootkey: corrupt registry file ?  No root key record located\n"));*/
1393    return NULL;
1394  }
[30]1395
[31]1396  DLIST_ADD( file->block_list, hbin );
[30]1397
[31]1398  return nk;           
[30]1399}
1400
1401
[33]1402/* XXX: An interator struct should be used instead, and this function
1403 *   should operate on it, so the state of iteration isn't stored in the
1404 * REGF_NK_REC struct itself.
1405 */
[30]1406/*******************************************************************
1407 This acts as an interator over the subkeys defined for a given
1408 NK record.  Remember that offsets are from the *first* HBIN block.
1409*******************************************************************/
1410REGF_NK_REC* regfio_fetch_subkey( REGF_FILE *file, REGF_NK_REC *nk )
1411{
[31]1412  REGF_NK_REC *subkey;
1413  REGF_HBIN   *hbin;
1414  uint32      nk_offset;
[30]1415
[31]1416  /* see if there is anything left to report */
[32]1417  if (!nk || (nk->subkeys_off==REGF_OFFSET_NONE) 
1418      || (nk->subkey_index >= nk->num_subkeys))
[31]1419    return NULL;
[30]1420
[31]1421  /* find the HBIN block which should contain the nk record */
1422  if(!(hbin
1423       = lookup_hbin_block(file, nk->subkeys.hashes[nk->subkey_index].nk_off )))
1424  {
1425    /*DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing offset [0x%x]\n",
1426      nk->subkeys.hashes[nk->subkey_index].nk_off));*/
1427    return NULL;
1428  }
[30]1429       
[31]1430  nk_offset = nk->subkeys.hashes[nk->subkey_index].nk_off;
[32]1431  if(!prs_set_offset(&hbin->ps, 
1432                     (HBIN_HDR_SIZE + nk_offset - hbin->first_hbin_off)))
[31]1433    return NULL;
[30]1434               
[31]1435  nk->subkey_index++;
[32]1436  if(!(subkey = (REGF_NK_REC*)zalloc(sizeof(REGF_NK_REC))))
[31]1437    return NULL;
[30]1438
[32]1439  if(!hbin_prs_key(file, hbin, subkey))
[31]1440    return NULL;
[32]1441
[31]1442  return subkey;
[30]1443}
Note: See TracBrowser for help on using the repository browser.