00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "includes.h"
00022 #include "regfio.h"
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 static int write_block( REGF_FILE *file, prs_struct *ps, uint32 offset )
00035 {
00036 int bytes_written, returned;
00037 char *buffer = prs_data_p( ps );
00038 uint32 buffer_size = prs_data_size( ps );
00039 SMB_STRUCT_STAT sbuf;
00040
00041 if ( file->fd == -1 )
00042 return -1;
00043
00044
00045
00046 if ( sys_fstat( file->fd, &sbuf ) ) {
00047 DEBUG(0,("write_block: stat() failed! (%s)\n", strerror(errno)));
00048 return -1;
00049 }
00050
00051 if ( lseek( file->fd, offset, SEEK_SET ) == -1 ) {
00052 DEBUG(0,("write_block: lseek() failed! (%s)\n", strerror(errno) ));
00053 return -1;
00054 }
00055
00056 bytes_written = returned = 0;
00057 while ( bytes_written < buffer_size ) {
00058 if ( (returned = write( file->fd, buffer+bytes_written, buffer_size-bytes_written )) == -1 ) {
00059 DEBUG(0,("write_block: write() failed! (%s)\n", strerror(errno) ));
00060 return False;
00061 }
00062
00063 bytes_written += returned;
00064 }
00065
00066 return bytes_written;
00067 }
00068
00069
00070
00071
00072 static int read_block( REGF_FILE *file, prs_struct *ps, uint32 file_offset, uint32 block_size )
00073 {
00074 int bytes_read, returned;
00075 char *buffer;
00076 SMB_STRUCT_STAT sbuf;
00077
00078
00079
00080 if ( sys_fstat( file->fd, &sbuf ) ) {
00081 DEBUG(0,("read_block: stat() failed! (%s)\n", strerror(errno)));
00082 return -1;
00083 }
00084
00085 if ( (size_t)file_offset >= sbuf.st_size )
00086 return -1;
00087
00088
00089
00090
00091 if ( block_size == 0 ) {
00092 char hdr[0x20];
00093
00094 if ( lseek( file->fd, file_offset, SEEK_SET ) == -1 ) {
00095 DEBUG(0,("read_block: lseek() failed! (%s)\n", strerror(errno) ));
00096 return -1;
00097 }
00098
00099 returned = read( file->fd, hdr, 0x20 );
00100 if ( (returned == -1) || (returned < 0x20) ) {
00101 DEBUG(0,("read_block: failed to read in HBIN header. Is the file corrupt?\n"));
00102 return -1;
00103 }
00104
00105
00106
00107 if ( strncmp( hdr, "hbin", HBIN_HDR_SIZE ) != 0 ) {
00108 DEBUG(0,("read_block: invalid block header!\n"));
00109 return -1;
00110 }
00111
00112 block_size = IVAL( hdr, 0x08 );
00113 }
00114
00115 DEBUG(10,("read_block: block_size == 0x%x\n", block_size ));
00116
00117
00118
00119 if ( lseek( file->fd, file_offset, SEEK_SET ) == -1 ) {
00120 DEBUG(0,("read_block: lseek() failed! (%s)\n", strerror(errno) ));
00121 return -1;
00122 }
00123
00124 prs_init( ps, block_size, file->mem_ctx, UNMARSHALL );
00125 buffer = prs_data_p( ps );
00126 bytes_read = returned = 0;
00127
00128 while ( bytes_read < block_size ) {
00129 if ( (returned = read( file->fd, buffer+bytes_read, block_size-bytes_read )) == -1 ) {
00130 DEBUG(0,("read_block: read() failed (%s)\n", strerror(errno) ));
00131 return False;
00132 }
00133 if ( (returned == 0) && (bytes_read < block_size) ) {
00134 DEBUG(0,("read_block: not a vald registry file ?\n" ));
00135 return False;
00136 }
00137
00138 bytes_read += returned;
00139 }
00140
00141 return bytes_read;
00142 }
00143
00144
00145
00146
00147 static BOOL write_hbin_block( REGF_FILE *file, REGF_HBIN *hbin )
00148 {
00149 if ( !hbin->dirty )
00150 return True;
00151
00152
00153
00154 if ( hbin->free_off != REGF_OFFSET_NONE ) {
00155 uint32 header = 0xffffffff;
00156
00157 if ( !prs_set_offset( &hbin->ps, hbin->free_off-sizeof(uint32) ) )
00158 return False;
00159 if ( !prs_uint32( "free_size", &hbin->ps, 0, &hbin->free_size ) )
00160 return False;
00161 if ( !prs_uint32( "free_header", &hbin->ps, 0, &header ) )
00162 return False;
00163 }
00164
00165 hbin->dirty = (write_block( file, &hbin->ps, hbin->file_off ) != -1);
00166
00167 return hbin->dirty;
00168 }
00169
00170
00171
00172
00173 static BOOL hbin_block_close( REGF_FILE *file, REGF_HBIN *hbin )
00174 {
00175 REGF_HBIN *p;
00176
00177
00178
00179 for ( p=file->block_list; p && p!=hbin; p=p->next )
00180 ;;
00181
00182 if ( p == hbin ) {
00183 DLIST_REMOVE( file->block_list, hbin );
00184 }
00185 else
00186 DEBUG(0,("hbin_block_close: block not in open list!\n"));
00187
00188 if ( !write_hbin_block( file, hbin ) )
00189 return False;
00190
00191 return True;
00192 }
00193
00194
00195
00196
00197 static BOOL prs_regf_block( const char *desc, prs_struct *ps, int depth, REGF_FILE *file )
00198 {
00199 prs_debug(ps, depth, desc, "prs_regf_block");
00200 depth++;
00201
00202 if ( !prs_uint8s( True, "header", ps, depth, (uint8*)file->header, sizeof( file->header )) )
00203 return False;
00204
00205
00206
00207 if ( !prs_uint32( "unknown1", ps, depth, &file->unknown1 ))
00208 return False;
00209 if ( !prs_uint32( "unknown1 (again)", ps, depth, &file->unknown1 ))
00210 return False;
00211
00212
00213
00214 if ( !prs_set_offset( ps, 0x0c ) )
00215 return False;
00216 if ( !smb_io_time( "modtime", &file->mtime, ps, depth ) )
00217 return False;
00218
00219
00220
00221 if ( !prs_uint32( "unknown2", ps, depth, &file->unknown2 ))
00222 return False;
00223 if ( !prs_uint32( "unknown3", ps, depth, &file->unknown3 ))
00224 return False;
00225 if ( !prs_uint32( "unknown4", ps, depth, &file->unknown4 ))
00226 return False;
00227 if ( !prs_uint32( "unknown5", ps, depth, &file->unknown5 ))
00228 return False;
00229
00230
00231
00232 if ( !prs_set_offset( ps, 0x24 ) )
00233 return False;
00234 if ( !prs_uint32( "data_offset", ps, depth, &file->data_offset ))
00235 return False;
00236 if ( !prs_uint32( "last_block", ps, depth, &file->last_block ))
00237 return False;
00238
00239
00240
00241 if ( !prs_uint32( "unknown6", ps, depth, &file->unknown6 ))
00242 return False;
00243
00244
00245
00246 if ( !prs_set_offset( ps, 0x01fc ) )
00247 return False;
00248 if ( !prs_uint32( "checksum", ps, depth, &file->checksum ))
00249 return False;
00250
00251 return True;
00252 }
00253
00254
00255
00256
00257 static BOOL prs_hbin_block( const char *desc, prs_struct *ps, int depth, REGF_HBIN *hbin )
00258 {
00259 uint32 block_size2;
00260
00261 prs_debug(ps, depth, desc, "prs_regf_block");
00262 depth++;
00263
00264 if ( !prs_uint8s( True, "header", ps, depth, (uint8*)hbin->header, sizeof( hbin->header )) )
00265 return False;
00266
00267 if ( !prs_uint32( "first_hbin_off", ps, depth, &hbin->first_hbin_off ))
00268 return False;
00269
00270
00271
00272
00273
00274 if ( !prs_uint32( "block_size", ps, depth, &hbin->block_size ))
00275 return False;
00276
00277 block_size2 = hbin->block_size;
00278 prs_set_offset( ps, 0x1c );
00279 if ( !prs_uint32( "block_size2", ps, depth, &block_size2 ))
00280 return False;
00281
00282 if ( MARSHALLING(ps) )
00283 hbin->dirty = True;
00284
00285
00286 return True;
00287 }
00288
00289
00290
00291
00292 static BOOL prs_nk_rec( const char *desc, prs_struct *ps, int depth, REGF_NK_REC *nk )
00293 {
00294 uint16 class_length, name_length;
00295 uint32 start;
00296 uint32 data_size, start_off, end_off;
00297 uint32 unknown_off = REGF_OFFSET_NONE;
00298
00299 nk->hbin_off = prs_offset( ps );
00300 start = nk->hbin_off;
00301
00302 prs_debug(ps, depth, desc, "prs_nk_rec");
00303 depth++;
00304
00305
00306
00307 if ( !prs_set_offset( ps, prs_offset(ps)-sizeof(uint32)) )
00308 return False;
00309 start_off = prs_offset( ps );
00310 if ( !prs_uint32( "rec_size", ps, depth, &nk->rec_size ))
00311 return False;
00312
00313 if ( !prs_uint8s( True, "header", ps, depth, (uint8*)nk->header, sizeof( nk->header )) )
00314 return False;
00315
00316 if ( !prs_uint16( "key_type", ps, depth, &nk->key_type ))
00317 return False;
00318 if ( !smb_io_time( "mtime", &nk->mtime, ps, depth ))
00319 return False;
00320
00321 if ( !prs_set_offset( ps, start+0x0010 ) )
00322 return False;
00323 if ( !prs_uint32( "parent_off", ps, depth, &nk->parent_off ))
00324 return False;
00325 if ( !prs_uint32( "num_subkeys", ps, depth, &nk->num_subkeys ))
00326 return False;
00327
00328 if ( !prs_set_offset( ps, start+0x001c ) )
00329 return False;
00330 if ( !prs_uint32( "subkeys_off", ps, depth, &nk->subkeys_off ))
00331 return False;
00332 if ( !prs_uint32( "unknown_off", ps, depth, &unknown_off) )
00333 return False;
00334
00335 if ( !prs_set_offset( ps, start+0x0024 ) )
00336 return False;
00337 if ( !prs_uint32( "num_values", ps, depth, &nk->num_values ))
00338 return False;
00339 if ( !prs_uint32( "values_off", ps, depth, &nk->values_off ))
00340 return False;
00341 if ( !prs_uint32( "sk_off", ps, depth, &nk->sk_off ))
00342 return False;
00343 if ( !prs_uint32( "classname_off", ps, depth, &nk->classname_off ))
00344 return False;
00345
00346 if ( !prs_uint32( "max_bytes_subkeyname", ps, depth, &nk->max_bytes_subkeyname))
00347 return False;
00348 if ( !prs_uint32( "max_bytes_subkeyclassname", ps, depth, &nk->max_bytes_subkeyclassname))
00349 return False;
00350 if ( !prs_uint32( "max_bytes_valuename", ps, depth, &nk->max_bytes_valuename))
00351 return False;
00352 if ( !prs_uint32( "max_bytes_value", ps, depth, &nk->max_bytes_value))
00353 return False;
00354 if ( !prs_uint32( "unknown index", ps, depth, &nk->unk_index))
00355 return False;
00356
00357 name_length = nk->keyname ? strlen(nk->keyname) : 0 ;
00358 class_length = nk->classname ? strlen(nk->classname) : 0 ;
00359 if ( !prs_uint16( "name_length", ps, depth, &name_length ))
00360 return False;
00361 if ( !prs_uint16( "class_length", ps, depth, &class_length ))
00362 return False;
00363
00364 if ( class_length ) {
00365 ;;
00366 }
00367
00368 if ( name_length ) {
00369 if ( UNMARSHALLING(ps) ) {
00370 if ( !(nk->keyname = PRS_ALLOC_MEM( ps, char, name_length+1 )) )
00371 return False;
00372 }
00373
00374 if ( !prs_uint8s( True, "name", ps, depth, (uint8*)nk->keyname, name_length) )
00375 return False;
00376
00377 if ( UNMARSHALLING(ps) )
00378 nk->keyname[name_length] = '\0';
00379 }
00380
00381 end_off = prs_offset( ps );
00382
00383
00384
00385 data_size = ((start_off - end_off) & 0xfffffff8 );
00386 if ( data_size > nk->rec_size )
00387 DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, nk->rec_size));
00388
00389 if ( MARSHALLING(ps) )
00390 nk->hbin->dirty = True;
00391
00392 return True;
00393 }
00394
00395
00396
00397
00398 static uint32 regf_block_checksum( prs_struct *ps )
00399 {
00400 char *buffer = prs_data_p( ps );
00401 uint32 checksum, x;
00402 int i;
00403
00404
00405
00406 checksum = x = 0;
00407
00408 for ( i=0; i<0x01FB; i+=4 ) {
00409 x = IVAL(buffer, i );
00410 checksum ^= x;
00411 }
00412
00413 return checksum;
00414 }
00415
00416
00417
00418
00419 static BOOL read_regf_block( REGF_FILE *file )
00420 {
00421 prs_struct ps;
00422 uint32 checksum;
00423
00424
00425
00426 if ( read_block( file, &ps, 0, REGF_BLOCKSIZE ) == -1 )
00427 return False;
00428
00429
00430
00431 if ( !prs_regf_block( "regf_header", &ps, 0, file ) )
00432 return False;
00433
00434 checksum = regf_block_checksum( &ps );
00435
00436 prs_mem_free( &ps );
00437
00438 if ( file->checksum != checksum ) {
00439 DEBUG(0,("read_regf_block: invalid checksum\n" ));
00440 return False;
00441 }
00442
00443 return True;
00444 }
00445
00446
00447
00448
00449 static REGF_HBIN* read_hbin_block( REGF_FILE *file, off_t offset )
00450 {
00451 REGF_HBIN *hbin;
00452 uint32 record_size, curr_off, block_size, header;
00453
00454 if ( !(hbin = TALLOC_ZERO_P(file->mem_ctx, REGF_HBIN)) )
00455 return NULL;
00456 hbin->file_off = offset;
00457 hbin->free_off = -1;
00458
00459 if ( read_block( file, &hbin->ps, offset, 0 ) == -1 )
00460 return NULL;
00461
00462 if ( !prs_hbin_block( "hbin", &hbin->ps, 0, hbin ) )
00463 return NULL;
00464
00465
00466
00467 block_size = prs_data_size( &hbin->ps );
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 if ( !prs_set_offset( &hbin->ps, file->data_offset+HBIN_HDR_SIZE-sizeof(uint32) ) )
00478 return False;
00479
00480 record_size = 0;
00481 header = 0;
00482 curr_off = prs_offset( &hbin->ps );
00483 while ( header != 0xffffffff ) {
00484
00485
00486
00487 curr_off = curr_off+record_size;
00488
00489
00490
00491
00492
00493
00494 if ( curr_off >= block_size ) {
00495 record_size = -1;
00496 curr_off = -1;
00497 break;
00498 }
00499
00500 if ( !prs_set_offset( &hbin->ps, curr_off) )
00501 return False;
00502
00503 if ( !prs_uint32( "rec_size", &hbin->ps, 0, &record_size ) )
00504 return False;
00505 if ( !prs_uint32( "header", &hbin->ps, 0, &header ) )
00506 return False;
00507
00508 SMB_ASSERT( record_size != 0 );
00509
00510 if ( record_size & 0x80000000 ) {
00511
00512 record_size = (record_size ^ 0xffffffff) + 1;
00513 }
00514 }
00515
00516
00517
00518 if ( header == 0xffffffff ) {
00519
00520
00521
00522
00523 hbin->free_off = curr_off + sizeof(uint32);
00524 hbin->free_size = record_size;
00525 }
00526
00527 DEBUG(10,("read_hbin_block: free space offset == 0x%x\n", hbin->free_off));
00528
00529 if ( !prs_set_offset( &hbin->ps, file->data_offset+HBIN_HDR_SIZE ) )
00530 return False;
00531
00532 return hbin;
00533 }
00534
00535
00536
00537
00538
00539
00540 static BOOL hbin_contains_offset( REGF_HBIN *hbin, uint32 offset )
00541 {
00542 if ( !hbin )
00543 return False;
00544
00545 if ( (offset > hbin->first_hbin_off) && (offset < (hbin->first_hbin_off+hbin->block_size)) )
00546 return True;
00547
00548 return False;
00549 }
00550
00551
00552
00553
00554
00555
00556 static REGF_HBIN* lookup_hbin_block( REGF_FILE *file, uint32 offset )
00557 {
00558 REGF_HBIN *hbin = NULL;
00559 uint32 block_off;
00560
00561
00562
00563 for ( hbin=file->block_list; hbin; hbin=hbin->next ) {
00564 DEBUG(10,("lookup_hbin_block: address = 0x%x [0x%lx]\n", hbin->file_off, (unsigned long)hbin ));
00565 if ( hbin_contains_offset( hbin, offset ) )
00566 return hbin;
00567 }
00568
00569 if ( !hbin ) {
00570
00571
00572 block_off = REGF_BLOCKSIZE;
00573 do {
00574
00575 if ( hbin )
00576 prs_mem_free( &hbin->ps );
00577
00578 hbin = read_hbin_block( file, block_off );
00579
00580 if ( hbin )
00581 block_off = hbin->file_off + hbin->block_size;
00582
00583 } while ( hbin && !hbin_contains_offset( hbin, offset ) );
00584 }
00585
00586 if ( hbin )
00587 DLIST_ADD( file->block_list, hbin );
00588
00589 return hbin;
00590 }
00591
00592
00593
00594
00595 static BOOL prs_hash_rec( const char *desc, prs_struct *ps, int depth, REGF_HASH_REC *hash )
00596 {
00597 prs_debug(ps, depth, desc, "prs_hash_rec");
00598 depth++;
00599
00600 if ( !prs_uint32( "nk_off", ps, depth, &hash->nk_off ))
00601 return False;
00602 if ( !prs_uint8s( True, "keycheck", ps, depth, hash->keycheck, sizeof( hash->keycheck )) )
00603 return False;
00604
00605 return True;
00606 }
00607
00608
00609
00610
00611 static BOOL hbin_prs_lf_records( const char *desc, REGF_HBIN *hbin, int depth, REGF_NK_REC *nk )
00612 {
00613 int i;
00614 REGF_LF_REC *lf = &nk->subkeys;
00615 uint32 data_size, start_off, end_off;
00616
00617 prs_debug(&hbin->ps, depth, desc, "prs_lf_records");
00618 depth++;
00619
00620
00621
00622 if ( nk->num_subkeys == 0 )
00623 return True;
00624
00625
00626
00627 if ( !prs_set_offset( &hbin->ps, nk->subkeys_off + HBIN_HDR_SIZE - hbin->first_hbin_off ) )
00628 return False;
00629
00630
00631
00632 if ( !prs_set_offset( &hbin->ps, prs_offset(&hbin->ps)-sizeof(uint32)) )
00633 return False;
00634 start_off = prs_offset( &hbin->ps );
00635 if ( !prs_uint32( "rec_size", &hbin->ps, depth, &lf->rec_size ))
00636 return False;
00637
00638 if ( !prs_uint8s( True, "header", &hbin->ps, depth, (uint8*)lf->header, sizeof( lf->header )) )
00639 return False;
00640
00641 if ( !prs_uint16( "num_keys", &hbin->ps, depth, &lf->num_keys))
00642 return False;
00643
00644 if ( UNMARSHALLING(&hbin->ps) ) {
00645 if (lf->num_keys) {
00646 if ( !(lf->hashes = PRS_ALLOC_MEM( &hbin->ps, REGF_HASH_REC, lf->num_keys )) )
00647 return False;
00648 } else {
00649 lf->hashes = NULL;
00650 }
00651 }
00652
00653 for ( i=0; i<lf->num_keys; i++ ) {
00654 if ( !prs_hash_rec( "hash_rec", &hbin->ps, depth, &lf->hashes[i] ) )
00655 return False;
00656 }
00657
00658 end_off = prs_offset( &hbin->ps );
00659
00660
00661
00662 data_size = ((start_off - end_off) & 0xfffffff8 );
00663 if ( data_size > lf->rec_size )
00664 DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, lf->rec_size));
00665
00666 if ( MARSHALLING(&hbin->ps) )
00667 hbin->dirty = True;
00668
00669 return True;
00670 }
00671
00672
00673
00674
00675 static BOOL hbin_prs_sk_rec( const char *desc, REGF_HBIN *hbin, int depth, REGF_SK_REC *sk )
00676 {
00677 prs_struct *ps = &hbin->ps;
00678 uint16 tag = 0xFFFF;
00679 uint32 data_size, start_off, end_off;
00680
00681
00682 prs_debug(ps, depth, desc, "hbin_prs_sk_rec");
00683 depth++;
00684
00685 if ( !prs_set_offset( &hbin->ps, sk->sk_off + HBIN_HDR_SIZE - hbin->first_hbin_off ) )
00686 return False;
00687
00688
00689
00690 if ( !prs_set_offset( &hbin->ps, prs_offset(&hbin->ps)-sizeof(uint32)) )
00691 return False;
00692 start_off = prs_offset( &hbin->ps );
00693 if ( !prs_uint32( "rec_size", &hbin->ps, depth, &sk->rec_size ))
00694 return False;
00695
00696 if ( !prs_uint8s( True, "header", ps, depth, (uint8*)sk->header, sizeof( sk->header )) )
00697 return False;
00698 if ( !prs_uint16( "tag", ps, depth, &tag))
00699 return False;
00700
00701 if ( !prs_uint32( "prev_sk_off", ps, depth, &sk->prev_sk_off))
00702 return False;
00703 if ( !prs_uint32( "next_sk_off", ps, depth, &sk->next_sk_off))
00704 return False;
00705 if ( !prs_uint32( "ref_count", ps, depth, &sk->ref_count))
00706 return False;
00707 if ( !prs_uint32( "size", ps, depth, &sk->size))
00708 return False;
00709
00710 if ( !sec_io_desc( "sec_desc", &sk->sec_desc, ps, depth ))
00711 return False;
00712
00713 end_off = prs_offset( &hbin->ps );
00714
00715
00716
00717 data_size = ((start_off - end_off) & 0xfffffff8 );
00718 if ( data_size > sk->rec_size )
00719 DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, sk->rec_size));
00720
00721 if ( MARSHALLING(&hbin->ps) )
00722 hbin->dirty = True;
00723
00724 return True;
00725 }
00726
00727
00728
00729
00730 static BOOL hbin_prs_vk_rec( const char *desc, REGF_HBIN *hbin, int depth, REGF_VK_REC *vk, REGF_FILE *file )
00731 {
00732 uint32 offset;
00733 uint16 name_length;
00734 prs_struct *ps = &hbin->ps;
00735 uint32 data_size, start_off, end_off;
00736
00737 prs_debug(ps, depth, desc, "prs_vk_rec");
00738 depth++;
00739
00740
00741
00742 if ( !prs_set_offset( &hbin->ps, prs_offset(&hbin->ps)-sizeof(uint32)) )
00743 return False;
00744 start_off = prs_offset( &hbin->ps );
00745 if ( !prs_uint32( "rec_size", &hbin->ps, depth, &vk->rec_size ))
00746 return False;
00747
00748 if ( !prs_uint8s( True, "header", ps, depth, (uint8*)vk->header, sizeof( vk->header )) )
00749 return False;
00750
00751 if ( MARSHALLING(&hbin->ps) )
00752 name_length = strlen(vk->valuename);
00753
00754 if ( !prs_uint16( "name_length", ps, depth, &name_length ))
00755 return False;
00756 if ( !prs_uint32( "data_size", ps, depth, &vk->data_size ))
00757 return False;
00758 if ( !prs_uint32( "data_off", ps, depth, &vk->data_off ))
00759 return False;
00760 if ( !prs_uint32( "type", ps, depth, &vk->type))
00761 return False;
00762 if ( !prs_uint16( "flag", ps, depth, &vk->flag))
00763 return False;
00764
00765 offset = prs_offset( ps );
00766 offset += 2;
00767 prs_set_offset( ps, offset );
00768
00769
00770
00771 if ( vk->flag&VK_FLAG_NAME_PRESENT ) {
00772
00773 if ( UNMARSHALLING(&hbin->ps) ) {
00774 if ( !(vk->valuename = PRS_ALLOC_MEM( ps, char, name_length+1 )))
00775 return False;
00776 }
00777 if ( !prs_uint8s( True, "name", ps, depth, (uint8*)vk->valuename, name_length ) )
00778 return False;
00779 }
00780
00781 end_off = prs_offset( &hbin->ps );
00782
00783
00784
00785 if ( vk->data_size != 0 ) {
00786 BOOL charmode = False;
00787
00788 if ( (vk->type == REG_SZ) || (vk->type == REG_MULTI_SZ) )
00789 charmode = True;
00790
00791
00792
00793 if ( !(vk->data_size & VK_DATA_IN_OFFSET) ) {
00794 REGF_HBIN *hblock = hbin;
00795 uint32 data_rec_size;
00796
00797 if ( UNMARSHALLING(&hbin->ps) ) {
00798 if ( !(vk->data = PRS_ALLOC_MEM( ps, uint8, vk->data_size) ) )
00799 return False;
00800 }
00801
00802
00803 if ( !hbin_contains_offset( hbin, vk->data_off ) ) {
00804 if ( !(hblock = lookup_hbin_block( file, vk->data_off )) )
00805 return False;
00806 }
00807 if ( !(prs_set_offset( &hblock->ps, (vk->data_off+HBIN_HDR_SIZE-hblock->first_hbin_off)-sizeof(uint32) )) )
00808 return False;
00809
00810 if ( MARSHALLING(&hblock->ps) ) {
00811 data_rec_size = ( (vk->data_size+sizeof(uint32)) & 0xfffffff8 ) + 8;
00812 data_rec_size = ( data_rec_size - 1 ) ^ 0xFFFFFFFF;
00813 }
00814 if ( !prs_uint32( "data_rec_size", &hblock->ps, depth, &data_rec_size ))
00815 return False;
00816 if ( !prs_uint8s( charmode, "data", &hblock->ps, depth, vk->data, vk->data_size) )
00817 return False;
00818
00819 if ( MARSHALLING(&hblock->ps) )
00820 hblock->dirty = True;
00821 }
00822 else {
00823 if ( !(vk->data = PRS_ALLOC_MEM( ps, uint8, 4 ) ) )
00824 return False;
00825 SIVAL( vk->data, 0, vk->data_off );
00826 }
00827
00828 }
00829
00830
00831
00832 data_size = ((start_off - end_off ) & 0xfffffff8 );
00833 if ( data_size != vk->rec_size )
00834 DEBUG(10,("prs_vk_rec: data_size check failed (0x%x < 0x%x)\n", data_size, vk->rec_size));
00835
00836 if ( MARSHALLING(&hbin->ps) )
00837 hbin->dirty = True;
00838
00839 return True;
00840 }
00841
00842
00843
00844
00845
00846
00847 static BOOL hbin_prs_vk_records( const char *desc, REGF_HBIN *hbin, int depth, REGF_NK_REC *nk, REGF_FILE *file )
00848 {
00849 int i;
00850 uint32 record_size;
00851
00852 prs_debug(&hbin->ps, depth, desc, "prs_vk_records");
00853 depth++;
00854
00855
00856
00857 if ( nk->num_values == 0 )
00858 return True;
00859
00860 if ( UNMARSHALLING(&hbin->ps) ) {
00861 if ( !(nk->values = PRS_ALLOC_MEM( &hbin->ps, REGF_VK_REC, nk->num_values ) ) )
00862 return False;
00863 }
00864
00865
00866
00867 if ( !prs_set_offset( &hbin->ps, nk->values_off+HBIN_HDR_SIZE-hbin->first_hbin_off-sizeof(uint32)) )
00868 return False;
00869
00870 if ( MARSHALLING( &hbin->ps) ) {
00871 record_size = ( ( nk->num_values * sizeof(uint32) ) & 0xfffffff8 ) + 8;
00872 record_size = (record_size - 1) ^ 0xFFFFFFFF;
00873 }
00874
00875 if ( !prs_uint32( "record_size", &hbin->ps, depth, &record_size ) )
00876 return False;
00877
00878 for ( i=0; i<nk->num_values; i++ ) {
00879 if ( !prs_uint32( "vk_off", &hbin->ps, depth, &nk->values[i].rec_off ) )
00880 return False;
00881 }
00882
00883 for ( i=0; i<nk->num_values; i++ ) {
00884 REGF_HBIN *sub_hbin = hbin;
00885 uint32 new_offset;
00886
00887 if ( !hbin_contains_offset( hbin, nk->values[i].rec_off ) ) {
00888 sub_hbin = lookup_hbin_block( file, nk->values[i].rec_off );
00889 if ( !sub_hbin ) {
00890 DEBUG(0,("hbin_prs_vk_records: Failed to find HBIN block containing offset [0x%x]\n",
00891 nk->values[i].hbin_off));
00892 return False;
00893 }
00894 }
00895
00896 new_offset = nk->values[i].rec_off + HBIN_HDR_SIZE - sub_hbin->first_hbin_off;
00897 if ( !prs_set_offset( &sub_hbin->ps, new_offset ) )
00898 return False;
00899 if ( !hbin_prs_vk_rec( "vk_rec", sub_hbin, depth, &nk->values[i], file ) )
00900 return False;
00901 }
00902
00903 if ( MARSHALLING(&hbin->ps) )
00904 hbin->dirty = True;
00905
00906
00907 return True;
00908 }
00909
00910
00911
00912
00913
00914 static REGF_SK_REC* find_sk_record_by_offset( REGF_FILE *file, uint32 offset )
00915 {
00916 REGF_SK_REC *p_sk;
00917
00918 for ( p_sk=file->sec_desc_list; p_sk; p_sk=p_sk->next ) {
00919 if ( p_sk->sk_off == offset )
00920 return p_sk;
00921 }
00922
00923 return NULL;
00924 }
00925
00926
00927
00928
00929 static REGF_SK_REC* find_sk_record_by_sec_desc( REGF_FILE *file, SEC_DESC *sd )
00930 {
00931 REGF_SK_REC *p;
00932
00933 for ( p=file->sec_desc_list; p; p=p->next ) {
00934 if ( sec_desc_equal( p->sec_desc, sd ) )
00935 return p;
00936 }
00937
00938
00939
00940 return NULL;
00941 }
00942
00943
00944
00945
00946 static BOOL hbin_prs_key( REGF_FILE *file, REGF_HBIN *hbin, REGF_NK_REC *nk )
00947 {
00948 int depth = 0;
00949 REGF_HBIN *sub_hbin;
00950
00951 prs_debug(&hbin->ps, depth, "", "fetch_key");
00952 depth++;
00953
00954
00955
00956 if ( !prs_nk_rec( "nk_rec", &hbin->ps, depth, nk ))
00957 return False;
00958
00959
00960
00961 if ( nk->num_values && (nk->values_off!=REGF_OFFSET_NONE) ) {
00962 sub_hbin = hbin;
00963 if ( !hbin_contains_offset( hbin, nk->values_off ) ) {
00964 sub_hbin = lookup_hbin_block( file, nk->values_off );
00965 if ( !sub_hbin ) {
00966 DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing value_list_offset [0x%x]\n",
00967 nk->values_off));
00968 return False;
00969 }
00970 }
00971
00972 if ( !hbin_prs_vk_records( "vk_rec", sub_hbin, depth, nk, file ))
00973 return False;
00974 }
00975
00976
00977
00978 if ( nk->num_subkeys && (nk->subkeys_off!=REGF_OFFSET_NONE) ) {
00979 sub_hbin = hbin;
00980 if ( !hbin_contains_offset( hbin, nk->subkeys_off ) ) {
00981 sub_hbin = lookup_hbin_block( file, nk->subkeys_off );
00982 if ( !sub_hbin ) {
00983 DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing subkey_offset [0x%x]\n",
00984 nk->subkeys_off));
00985 return False;
00986 }
00987 }
00988
00989 if ( !hbin_prs_lf_records( "lf_rec", sub_hbin, depth, nk ))
00990 return False;
00991 }
00992
00993
00994
00995 if ( (nk->sk_off!=REGF_OFFSET_NONE) && !( nk->sec_desc = find_sk_record_by_offset( file, nk->sk_off )) ) {
00996
00997 sub_hbin = hbin;
00998 if ( !hbin_contains_offset( hbin, nk->sk_off ) ) {
00999 sub_hbin = lookup_hbin_block( file, nk->sk_off );
01000 if ( !sub_hbin ) {
01001 DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing sk_offset [0x%x]\n",
01002 nk->subkeys_off));
01003 return False;
01004 }
01005 }
01006
01007 if ( !(nk->sec_desc = TALLOC_ZERO_P( file->mem_ctx, REGF_SK_REC )) )
01008 return False;
01009 nk->sec_desc->sk_off = nk->sk_off;
01010 if ( !hbin_prs_sk_rec( "sk_rec", sub_hbin, depth, nk->sec_desc ))
01011 return False;
01012
01013
01014
01015 nk->sec_desc->sk_off = nk->sk_off;
01016 DLIST_ADD( file->sec_desc_list, nk->sec_desc );
01017 }
01018
01019 return True;
01020 }
01021
01022
01023
01024
01025 static BOOL next_record( REGF_HBIN *hbin, const char *hdr, BOOL *eob )
01026 {
01027 uint8 header[REC_HDR_SIZE];
01028 uint32 record_size;
01029 uint32 curr_off, block_size;
01030 BOOL found = False;
01031 prs_struct *ps = &hbin->ps;
01032
01033 curr_off = prs_offset( ps );
01034 if ( curr_off == 0 )
01035 prs_set_offset( ps, HBIN_HEADER_REC_SIZE );
01036
01037
01038
01039
01040 curr_off -= sizeof(uint32);
01041
01042 block_size = prs_data_size( ps );
01043 record_size = 0;
01044 memset( header, 0x0, sizeof(uint8)*REC_HDR_SIZE );
01045 while ( !found ) {
01046
01047 curr_off = curr_off+record_size;
01048 if ( curr_off >= block_size )
01049 break;
01050
01051 if ( !prs_set_offset( &hbin->ps, curr_off) )
01052 return False;
01053
01054 if ( !prs_uint32( "record_size", ps, 0, &record_size ) )
01055 return False;
01056 if ( !prs_uint8s( True, "header", ps, 0, header, REC_HDR_SIZE ) )
01057 return False;
01058
01059 if ( record_size & 0x80000000 ) {
01060
01061 record_size = (record_size ^ 0xffffffff) + 1;
01062 }
01063
01064 if ( memcmp( header, hdr, REC_HDR_SIZE ) == 0 ) {
01065 found = True;
01066 curr_off += sizeof(uint32);
01067 }
01068 }
01069
01070
01071
01072
01073 if ( !found ) {
01074 prs_set_offset( &hbin->ps, prs_data_size(&hbin->ps) );
01075 *eob = True;
01076 return False;
01077 }
01078
01079 if ( !prs_set_offset( ps, curr_off ) )
01080 return False;
01081
01082 return True;
01083 }
01084
01085
01086
01087
01088 static BOOL next_nk_record( REGF_FILE *file, REGF_HBIN *hbin, REGF_NK_REC *nk, BOOL *eob )
01089 {
01090 if ( next_record( hbin, "nk", eob ) && hbin_prs_key( file, hbin, nk ) )
01091 return True;
01092
01093 return False;
01094 }
01095
01096
01097
01098
01099
01100
01101 static BOOL init_regf_block( REGF_FILE *file )
01102 {
01103 prs_struct ps;
01104 BOOL result = True;
01105
01106 if ( !prs_init( &ps, REGF_BLOCKSIZE, file->mem_ctx, MARSHALL ) )
01107 return False;
01108
01109 memcpy( file->header, "regf", REGF_HDR_SIZE );
01110 file->data_offset = 0x20;
01111 file->last_block = 0x1000;
01112
01113
01114
01115 unix_to_nt_time( &file->mtime, time(NULL) );
01116
01117
01118
01119 file->unknown1 = 0x2;
01120 file->unknown2 = 0x1;
01121 file->unknown3 = 0x3;
01122 file->unknown4 = 0x0;
01123 file->unknown5 = 0x1;
01124 file->unknown6 = 0x1;
01125
01126
01127
01128 if ( !prs_regf_block( "regf_header", &ps, 0, file ) ) {
01129 result = False;
01130 goto out;
01131 }
01132
01133
01134
01135
01136 file->checksum = regf_block_checksum( &ps );
01137 prs_set_offset( &ps, 0 );
01138 if ( !prs_regf_block( "regf_header", &ps, 0, file ) ) {
01139 result = False;
01140 goto out;
01141 }
01142
01143 if ( write_block( file, &ps, 0 ) == -1 ) {
01144 DEBUG(0,("init_regf_block: Failed to initialize registry header block!\n"));
01145 result = False;
01146 goto out;
01147 }
01148
01149 out:
01150 prs_mem_free( &ps );
01151
01152 return result;
01153 }
01154
01155
01156
01157
01158
01159 REGF_FILE* regfio_open( const char *filename, int flags, int mode )
01160 {
01161 REGF_FILE *rb;
01162
01163 if ( !(rb = SMB_MALLOC_P(REGF_FILE)) ) {
01164 DEBUG(0,("ERROR allocating memory\n"));
01165 return NULL;
01166 }
01167 ZERO_STRUCTP( rb );
01168 rb->fd = -1;
01169
01170 if ( !(rb->mem_ctx = talloc_init( "read_regf_block" )) ) {
01171 regfio_close( rb );
01172 return NULL;
01173 }
01174
01175 rb->open_flags = flags;
01176
01177
01178
01179 if ( (rb->fd = open(filename, flags, mode)) == -1 ) {
01180 DEBUG(0,("regfio_open: failure to open %s (%s)\n", filename, strerror(errno)));
01181 regfio_close( rb );
01182 return NULL;
01183 }
01184
01185
01186
01187 if ( flags & (O_CREAT|O_TRUNC) ) {
01188 if ( !init_regf_block( rb ) ) {
01189 DEBUG(0,("regfio_open: Failed to read initial REGF block\n"));
01190 regfio_close( rb );
01191 return NULL;
01192 }
01193
01194
01195 return rb;
01196 }
01197
01198
01199
01200 if ( !read_regf_block( rb ) ) {
01201 DEBUG(0,("regfio_open: Failed to read initial REGF block\n"));
01202 regfio_close( rb );
01203 return NULL;
01204 }
01205
01206
01207
01208 return rb;
01209 }
01210
01211
01212
01213
01214 static void regfio_mem_free( REGF_FILE *file )
01215 {
01216
01217
01218 if ( file && file->mem_ctx )
01219 talloc_destroy( file->mem_ctx );
01220 }
01221
01222
01223
01224
01225 int regfio_close( REGF_FILE *file )
01226 {
01227 int fd;
01228
01229
01230
01231 if ( file->open_flags & (O_WRONLY|O_RDWR) ) {
01232 prs_struct ps;
01233 REGF_SK_REC *sk;
01234
01235
01236
01237 for ( sk=file->sec_desc_list; sk; sk=sk->next ) {
01238 hbin_prs_sk_rec( "sk_rec", sk->hbin, 0, sk );
01239 }
01240
01241
01242
01243 while ( file->block_list ) {
01244 hbin_block_close( file, file->block_list );
01245 }
01246
01247 ZERO_STRUCT( ps );
01248
01249 unix_to_nt_time( &file->mtime, time(NULL) );
01250
01251 if ( read_block( file, &ps, 0, REGF_BLOCKSIZE ) != -1 ) {
01252
01253 prs_switch_type( &ps, MARSHALL );
01254
01255
01256
01257 prs_set_offset( &ps, 0 );
01258 prs_regf_block( "regf_blocK", &ps, 0, file );
01259 file->checksum = regf_block_checksum( &ps );
01260 prs_set_offset( &ps, 0 );
01261 prs_regf_block( "regf_blocK", &ps, 0, file );
01262
01263
01264 if ( write_block( file, &ps, 0 ) == -1 )
01265 DEBUG(0,("regfio_close: failed to update the regf header block!\n"));
01266 }
01267
01268 prs_mem_free( &ps );
01269 }
01270
01271 regfio_mem_free( file );
01272
01273
01274
01275 if ( !file || (file->fd == -1) )
01276 return 0;
01277
01278 fd = file->fd;
01279 file->fd = -1;
01280 SAFE_FREE( file );
01281
01282 return close( fd );
01283 }
01284
01285
01286
01287
01288 static void regfio_flush( REGF_FILE *file )
01289 {
01290 REGF_HBIN *hbin;
01291
01292 for ( hbin=file->block_list; hbin; hbin=hbin->next ) {
01293 write_hbin_block( file, hbin );
01294 }
01295 }
01296
01297
01298
01299
01300
01301
01302 REGF_NK_REC* regfio_rootkey( REGF_FILE *file )
01303 {
01304 REGF_NK_REC *nk;
01305 REGF_HBIN *hbin;
01306 uint32 offset = REGF_BLOCKSIZE;
01307 BOOL found = False;
01308 BOOL eob;
01309
01310 if ( !file )
01311 return NULL;
01312
01313 if ( !(nk = TALLOC_ZERO_P( file->mem_ctx, REGF_NK_REC )) ) {
01314 DEBUG(0,("regfio_rootkey: talloc() failed!\n"));
01315 return NULL;
01316 }
01317
01318
01319
01320
01321
01322
01323 while ( (hbin = read_hbin_block( file, offset )) ) {
01324 eob = False;
01325
01326 while ( !eob) {
01327 if ( next_nk_record( file, hbin, nk, &eob ) ) {
01328 if ( nk->key_type == NK_TYPE_ROOTKEY ) {
01329 found = True;
01330 break;
01331 }
01332 }
01333 prs_mem_free( &hbin->ps );
01334 }
01335
01336 if ( found )
01337 break;
01338
01339 offset += hbin->block_size;
01340 }
01341
01342 if ( !found ) {
01343 DEBUG(0,("regfio_rootkey: corrupt registry file ? No root key record located\n"));
01344 return NULL;
01345 }
01346
01347 DLIST_ADD( file->block_list, hbin );
01348
01349 return nk;
01350 }
01351
01352
01353
01354
01355
01356
01357 REGF_NK_REC* regfio_fetch_subkey( REGF_FILE *file, REGF_NK_REC *nk )
01358 {
01359 REGF_NK_REC *subkey;
01360 REGF_HBIN *hbin;
01361 uint32 nk_offset;
01362
01363
01364
01365 if ( !nk || (nk->subkeys_off==REGF_OFFSET_NONE) || (nk->subkey_index >= nk->num_subkeys) )
01366 return NULL;
01367
01368
01369
01370 if ( !(hbin = lookup_hbin_block( file, nk->subkeys.hashes[nk->subkey_index].nk_off )) ) {
01371 DEBUG(0,("hbin_prs_key: Failed to find HBIN block containing offset [0x%x]\n",
01372 nk->subkeys.hashes[nk->subkey_index].nk_off));
01373 return NULL;
01374 }
01375
01376 nk_offset = nk->subkeys.hashes[nk->subkey_index].nk_off;
01377 if ( !prs_set_offset( &hbin->ps, (HBIN_HDR_SIZE + nk_offset - hbin->first_hbin_off) ) )
01378 return NULL;
01379
01380 nk->subkey_index++;
01381 if ( !(subkey = TALLOC_ZERO_P( file->mem_ctx, REGF_NK_REC )) )
01382 return NULL;
01383
01384 if ( !hbin_prs_key( file, hbin, subkey ) )
01385 return NULL;
01386
01387 return subkey;
01388 }
01389
01390
01391
01392
01393
01394 static REGF_HBIN* regf_hbin_allocate( REGF_FILE *file, uint32 block_size )
01395 {
01396 REGF_HBIN *hbin;
01397 SMB_STRUCT_STAT sbuf;
01398
01399 if ( !(hbin = TALLOC_ZERO_P( file->mem_ctx, REGF_HBIN )) )
01400 return NULL;
01401
01402 memcpy( hbin->header, "hbin", sizeof(HBIN_HDR_SIZE) );
01403
01404
01405 if ( sys_fstat( file->fd, &sbuf ) ) {
01406 DEBUG(0,("regf_hbin_allocate: stat() failed! (%s)\n", strerror(errno)));
01407 return NULL;
01408 }
01409
01410 hbin->file_off = sbuf.st_size;
01411
01412 hbin->free_off = HBIN_HEADER_REC_SIZE;
01413 hbin->free_size = block_size - hbin->free_off + sizeof(uint32);;
01414
01415 hbin->block_size = block_size;
01416 hbin->first_hbin_off = hbin->file_off - REGF_BLOCKSIZE;
01417
01418 if ( !prs_init( &hbin->ps, block_size, file->mem_ctx, MARSHALL ) )
01419 return NULL;
01420
01421 if ( !prs_hbin_block( "new_hbin", &hbin->ps, 0, hbin ) )
01422 return NULL;
01423
01424 if ( !write_hbin_block( file, hbin ) )
01425 return NULL;
01426
01427 file->last_block = hbin->file_off;
01428
01429 return hbin;
01430 }
01431
01432
01433
01434
01435 static void update_free_space( REGF_HBIN *hbin, uint32 size_used )
01436 {
01437 hbin->free_off += size_used;
01438 hbin->free_size -= size_used;
01439
01440 if ( hbin->free_off >= hbin->block_size ) {
01441 hbin->free_off = REGF_OFFSET_NONE;
01442 }
01443
01444 return;
01445 }
01446
01447
01448
01449
01450 static REGF_HBIN* find_free_space( REGF_FILE *file, uint32 size )
01451 {
01452 REGF_HBIN *hbin, *p_hbin;
01453 uint32 block_off;
01454 BOOL cached;
01455
01456
01457
01458 for ( hbin=file->block_list; hbin!=NULL; hbin=hbin->next ) {
01459
01460
01461 if ( hbin->free_off == REGF_OFFSET_NONE )
01462 continue;
01463
01464
01465
01466 if ( (hbin->block_size - hbin->free_off) >= size ) {
01467 DLIST_PROMOTE( file->block_list, hbin );
01468 goto done;
01469 }
01470 }
01471
01472
01473
01474
01475 block_off = REGF_BLOCKSIZE;
01476 do {
01477
01478 cached = False;
01479 if ( hbin )
01480 prs_mem_free( &hbin->ps );
01481
01482 hbin = read_hbin_block( file, block_off );
01483
01484 if ( hbin ) {
01485
01486
01487
01488 for ( p_hbin=file->block_list; p_hbin!=NULL; p_hbin=p_hbin->next ) {
01489 if ( p_hbin->file_off == hbin->file_off ) {
01490 cached = True;
01491 break;
01492 }
01493 }
01494
01495 block_off = hbin->file_off + hbin->block_size;
01496
01497 if ( cached ) {
01498 prs_mem_free( &hbin->ps );
01499 hbin = NULL;
01500 continue;
01501 }
01502 }
01503
01504 } while ( cached || (hbin && (hbin->free_size < size)) );
01505
01506
01507
01508 if ( !hbin ) {
01509 uint32 alloc_size;
01510
01511
01512
01513 alloc_size = (((size+HBIN_HEADER_REC_SIZE) / REGF_ALLOC_BLOCK ) + 1 ) * REGF_ALLOC_BLOCK;
01514
01515 if ( !(hbin = regf_hbin_allocate( file, alloc_size )) ) {
01516 DEBUG(0,("find_free_space: regf_hbin_allocate() failed!\n"));
01517 return NULL;
01518 }
01519 DLIST_ADD( file->block_list, hbin );
01520 }
01521
01522 done:
01523
01524
01525 if ( !prs_set_offset( &hbin->ps, hbin->free_off-sizeof(uint32) ) )
01526 return NULL;
01527
01528
01529
01530
01531
01532 if ( !prs_uint32("allocated_size", &hbin->ps, 0, &size) )
01533 return False;
01534
01535 update_free_space( hbin, size );
01536
01537 return hbin;
01538 }
01539
01540
01541
01542
01543 static uint32 sk_record_data_size( SEC_DESC * sd )
01544 {
01545 uint32 size, size_mod8;
01546
01547 size_mod8 = 0;
01548
01549
01550
01551 size = sizeof(uint32)*5 + sec_desc_size( sd ) + sizeof(uint32);
01552
01553
01554 size_mod8 = size & 0xfffffff8;
01555 if ( size_mod8 < size )
01556 size_mod8 += 8;
01557
01558 return size_mod8;
01559 }
01560
01561
01562
01563
01564 static uint32 vk_record_data_size( REGF_VK_REC *vk )
01565 {
01566 uint32 size, size_mod8;
01567
01568 size_mod8 = 0;
01569
01570
01571
01572 size = REC_HDR_SIZE + (sizeof(uint16)*3) + (sizeof(uint32)*3) + sizeof(uint32);
01573
01574 if ( vk->valuename )
01575 size += strlen(vk->valuename);
01576
01577
01578 size_mod8 = size & 0xfffffff8;
01579 if ( size_mod8 < size )
01580 size_mod8 += 8;
01581
01582 return size_mod8;
01583 }
01584
01585
01586
01587
01588 static uint32 lf_record_data_size( uint32 num_keys )
01589 {
01590 uint32 size, size_mod8;
01591
01592 size_mod8 = 0;
01593
01594
01595
01596 size = REC_HDR_SIZE + sizeof(uint16) + (sizeof(REGF_HASH_REC) * num_keys) + sizeof(uint32);
01597
01598
01599 size_mod8 = size & 0xfffffff8;
01600 if ( size_mod8 < size )
01601 size_mod8 += 8;
01602
01603 return size_mod8;
01604 }
01605
01606
01607
01608
01609 static uint32 nk_record_data_size( REGF_NK_REC *nk )
01610 {
01611 uint32 size, size_mod8;
01612
01613 size_mod8 = 0;
01614
01615
01616
01617 size = 0x4c + strlen(nk->keyname) + sizeof(uint32);
01618
01619 if ( nk->classname )
01620 size += strlen( nk->classname );
01621
01622
01623 size_mod8 = size & 0xfffffff8;
01624 if ( size_mod8 < size )
01625 size_mod8 += 8;
01626
01627 return size_mod8;
01628 }
01629
01630
01631
01632
01633 static BOOL create_vk_record( REGF_FILE *file, REGF_VK_REC *vk, REGISTRY_VALUE *value )
01634 {
01635 char *name = regval_name(value);
01636 REGF_HBIN *data_hbin;
01637
01638 ZERO_STRUCTP( vk );
01639
01640 memcpy( vk->header, "vk", REC_HDR_SIZE );
01641
01642 if ( name ) {
01643 vk->valuename = talloc_strdup( file->mem_ctx, regval_name(value) );
01644 vk->flag = VK_FLAG_NAME_PRESENT;
01645 }
01646
01647 vk->data_size = regval_size( value );
01648 vk->type = regval_type( value );
01649
01650 if ( vk->data_size > sizeof(uint32) ) {
01651 uint32 data_size = ( (vk->data_size+sizeof(uint32)) & 0xfffffff8 ) + 8;
01652
01653 vk->data = (uint8 *)TALLOC_MEMDUP( file->mem_ctx,
01654 regval_data_p(value),
01655 vk->data_size );
01656 if (vk->data == NULL) {
01657 return False;
01658 }
01659
01660
01661
01662
01663 if ((data_hbin = find_free_space(file, data_size )) == NULL) {
01664 return False;
01665 }
01666 vk->data_off = prs_offset( &data_hbin->ps ) + data_hbin->first_hbin_off - HBIN_HDR_SIZE;
01667 }
01668 else {
01669
01670
01671 if ( vk->data_size != 0 )
01672 memcpy( &vk->data_off, regval_data_p(value), sizeof(uint32) );
01673 vk->data_size |= VK_DATA_IN_OFFSET;
01674 }
01675
01676 return True;
01677 }
01678
01679
01680
01681
01682 static int hashrec_cmp( REGF_HASH_REC *h1, REGF_HASH_REC *h2 )
01683 {
01684 return StrCaseCmp( h1->fullname, h2->fullname );
01685 }
01686
01687
01688
01689
01690 REGF_NK_REC* regfio_write_key( REGF_FILE *file, const char *name,
01691 REGVAL_CTR *values, REGSUBKEY_CTR *subkeys,
01692 SEC_DESC *sec_desc, REGF_NK_REC *parent )
01693 {
01694 REGF_NK_REC *nk;
01695 REGF_HBIN *vlist_hbin = NULL;
01696 uint32 size;
01697
01698 if ( !(nk = TALLOC_ZERO_P( file->mem_ctx, REGF_NK_REC )) )
01699 return NULL;
01700
01701 memcpy( nk->header, "nk", REC_HDR_SIZE );
01702
01703 if ( !parent )
01704 nk->key_type = NK_TYPE_ROOTKEY;
01705 else
01706 nk->key_type = NK_TYPE_NORMALKEY;
01707
01708
01709
01710 nk->parent_off = parent ? (parent->hbin_off + parent->hbin->file_off - REGF_BLOCKSIZE - HBIN_HDR_SIZE ) : REGF_OFFSET_NONE;
01711
01712
01713
01714 nk->classname_off = REGF_OFFSET_NONE;
01715 nk->classname = NULL;
01716 nk->keyname = talloc_strdup( file->mem_ctx, name );
01717
01718
01719
01720 unix_to_nt_time( &nk->mtime, time(NULL) );
01721
01722
01723
01724 size = nk_record_data_size( nk );
01725 nk->rec_size = ( size - 1 ) ^ 0XFFFFFFFF;
01726 if ((nk->hbin = find_free_space( file, size )) == NULL) {
01727 return NULL;
01728 }
01729 nk->hbin_off = prs_offset( &nk->hbin->ps );
01730
01731
01732
01733 if ( parent ) {
01734 REGF_HASH_REC *hash = &parent->subkeys.hashes[parent->subkey_index];
01735
01736 hash->nk_off = prs_offset( &nk->hbin->ps ) + nk->hbin->first_hbin_off - HBIN_HDR_SIZE;
01737 memcpy( hash->keycheck, name, sizeof(uint32) );
01738 hash->fullname = talloc_strdup( file->mem_ctx, name );
01739 parent->subkey_index++;
01740
01741
01742
01743 qsort( parent->subkeys.hashes, parent->subkey_index, sizeof(REGF_HASH_REC), QSORT_CAST hashrec_cmp );
01744
01745 if ( !hbin_prs_lf_records( "lf_rec", parent->subkeys.hbin, 0, parent ) )
01746 return False;
01747 }
01748
01749
01750
01751 nk->sk_off = REGF_OFFSET_NONE;
01752 if ( sec_desc ) {
01753 uint32 sk_size = sk_record_data_size( sec_desc );
01754 REGF_HBIN *sk_hbin;
01755
01756
01757
01758 if ( (nk->sec_desc = find_sk_record_by_sec_desc( file, sec_desc )) == NULL ) {
01759
01760
01761 if (!(sk_hbin = find_free_space( file, sk_size ))) {
01762 return NULL;
01763 }
01764
01765 if ( !(nk->sec_desc = TALLOC_ZERO_P( file->mem_ctx, REGF_SK_REC )) )
01766 return NULL;
01767
01768
01769
01770
01771 memcpy( nk->sec_desc->header, "sk", REC_HDR_SIZE );
01772 nk->sec_desc->hbin = sk_hbin;
01773 nk->sec_desc->hbin_off = prs_offset( &sk_hbin->ps );
01774 nk->sec_desc->sk_off = prs_offset( &sk_hbin->ps ) + sk_hbin->first_hbin_off - HBIN_HDR_SIZE;
01775 nk->sec_desc->rec_size = (sk_size-1) ^ 0xFFFFFFFF;
01776
01777 nk->sec_desc->sec_desc = sec_desc;
01778 nk->sec_desc->ref_count = 0;
01779
01780
01781 nk->sec_desc->size = sec_desc_size(sec_desc) + sizeof(uint32);
01782
01783 DLIST_ADD_END( file->sec_desc_list, nk->sec_desc, REGF_SK_REC *);
01784
01785
01786
01787
01788
01789 if ( nk->sec_desc->prev ) {
01790 REGF_SK_REC *prev = nk->sec_desc->prev;
01791
01792 nk->sec_desc->prev_sk_off = prev->hbin_off + prev->hbin->first_hbin_off - HBIN_HDR_SIZE;
01793 prev->next_sk_off = nk->sec_desc->sk_off;
01794
01795
01796 nk->sec_desc->next_sk_off = file->sec_desc_list->sk_off;
01797
01798
01799 file->sec_desc_list->prev_sk_off = nk->sec_desc->sk_off;
01800 } else {
01801 nk->sec_desc->prev_sk_off = nk->sec_desc->sk_off;
01802 nk->sec_desc->next_sk_off = nk->sec_desc->sk_off;
01803 }
01804 }
01805
01806
01807
01808 nk->sk_off = nk->sec_desc->sk_off;
01809 nk->sec_desc->ref_count++;
01810 }
01811
01812
01813
01814 nk->subkeys_off = REGF_OFFSET_NONE;
01815 if ( (nk->num_subkeys = regsubkey_ctr_numkeys( subkeys )) != 0 ) {
01816 uint32 lf_size = lf_record_data_size( nk->num_subkeys );
01817 uint32 namelen;
01818 int i;
01819
01820 if (!(nk->subkeys.hbin = find_free_space( file, lf_size ))) {
01821 return NULL;
01822 }
01823 nk->subkeys.hbin_off = prs_offset( &nk->subkeys.hbin->ps );
01824 nk->subkeys.rec_size = (lf_size-1) ^ 0xFFFFFFFF;
01825 nk->subkeys_off = prs_offset( &nk->subkeys.hbin->ps ) + nk->subkeys.hbin->first_hbin_off - HBIN_HDR_SIZE;
01826
01827 memcpy( nk->subkeys.header, "lf", REC_HDR_SIZE );
01828
01829 nk->subkeys.num_keys = nk->num_subkeys;
01830 if (nk->subkeys.num_keys) {
01831 if ( !(nk->subkeys.hashes = TALLOC_ZERO_ARRAY( file->mem_ctx, REGF_HASH_REC, nk->subkeys.num_keys )) )
01832 return NULL;
01833 } else {
01834 nk->subkeys.hashes = NULL;
01835 }
01836 nk->subkey_index = 0;
01837
01838
01839 for ( i=0; i<nk->num_subkeys; i++ ) {
01840 namelen = strlen( regsubkey_ctr_specific_key(subkeys, i) );
01841 if ( namelen*2 > nk->max_bytes_subkeyname )
01842 nk->max_bytes_subkeyname = namelen * 2;
01843 }
01844 }
01845
01846
01847
01848 nk->values_off = REGF_OFFSET_NONE;
01849 if ( (nk->num_values = regval_ctr_numvals( values )) != 0 ) {
01850 uint32 vlist_size = ( ( nk->num_values * sizeof(uint32) ) & 0xfffffff8 ) + 8;
01851 int i;
01852
01853 if (!(vlist_hbin = find_free_space( file, vlist_size ))) {
01854 return NULL;
01855 }
01856 nk->values_off = prs_offset( &vlist_hbin->ps ) + vlist_hbin->first_hbin_off - HBIN_HDR_SIZE;
01857
01858 if (nk->num_values) {
01859 if ( !(nk->values = TALLOC_ARRAY( file->mem_ctx, REGF_VK_REC, nk->num_values )) )
01860 return NULL;
01861 } else {
01862 nk->values = NULL;
01863 }
01864
01865
01866
01867 for ( i=0; i<nk->num_values; i++ ) {
01868 uint32 vk_size, namelen, datalen;
01869 REGISTRY_VALUE *r;
01870
01871 r = regval_ctr_specific_value( values, i );
01872 create_vk_record( file, &nk->values[i], r );
01873 vk_size = vk_record_data_size( &nk->values[i] );
01874 nk->values[i].hbin = find_free_space( file, vk_size );
01875 nk->values[i].hbin_off = prs_offset( &nk->values[i].hbin->ps );
01876 nk->values[i].rec_size = ( vk_size - 1 ) ^ 0xFFFFFFFF;
01877 nk->values[i].rec_off = prs_offset( &nk->values[i].hbin->ps )
01878 + nk->values[i].hbin->first_hbin_off
01879 - HBIN_HDR_SIZE;
01880
01881
01882
01883 namelen = strlen( regval_name(r) );
01884 if ( namelen*2 > nk->max_bytes_valuename )
01885 nk->max_bytes_valuename = namelen * 2;
01886
01887 datalen = regval_size( r );
01888 if ( datalen > nk->max_bytes_value )
01889 nk->max_bytes_value = datalen;
01890 }
01891 }
01892
01893
01894
01895 prs_set_offset( &nk->hbin->ps, nk->hbin_off );
01896 if ( !prs_nk_rec( "nk_rec", &nk->hbin->ps, 0, nk ) )
01897 return False;
01898
01899 if ( nk->num_values ) {
01900 if ( !hbin_prs_vk_records( "vk_records", vlist_hbin, 0, nk, file ) )
01901 return False;
01902 }
01903
01904
01905 regfio_flush( file );
01906
01907 return nk;
01908 }
01909