- Timestamp:
- 02/26/08 20:04:14 (17 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/devel/winntreg.txt
r26 r97 110 110 0x0002 Word for the root-key: 0x2C, otherwise 0x20 //key symbolic links 0x10. Nigel 111 111 0x0004 Q-Word write-date/time in windows nt notation 112 0x000C D-Word UNKNOWN // added by TDM 112 113 0x0010 D-Word Offset of Owner/Parent key 113 114 0x0014 D-Word number of sub-Keys 115 0x0018 D-Word UNKNOWN // added by TDM 114 116 0x001C D-Word Offset of the sub-key lf-Records 117 0x0020 D-Word UNKNOWN // added by TDM 115 118 0x0024 D-Word number of values 116 119 0x0028 D-Word Offset of the Value-List -
trunk/include/regfi.h
r84 r97 72 72 73 73 #define REGF_BLOCKSIZE 0x1000 74 #define REGF_ALLOC_BLOCK 0x1000 74 #define REGF_ALLOC_BLOCK 0x1000 /* Minimum allocation unit for hbins */ 75 75 #define REGF_MAX_DEPTH 512 76 76 77 77 /* header sizes for various records */ 78 78 79 #define REGF_ HDR_SIZE 480 #define HBIN_ HDR_SIZE 481 #define HBIN_HEADER_REC_SIZE 0x2 479 #define REGF_MAGIC_SIZE 4 80 #define HBIN_MAGIC_SIZE 4 81 #define HBIN_HEADER_REC_SIZE 0x20 82 82 #define REC_HDR_SIZE 2 83 83 … … 103 103 /* HBIN block */ 104 104 struct regf_hbin; 105 typedef struct regf_hbin { 105 typedef struct regf_hbin 106 { 106 107 struct regf_hbin* prev; 107 108 struct regf_hbin* next; 108 109 uint32 file_off; /* my offset in the registry file */ 109 uint32 free_off; /* offset to free space within the hbin record */110 uint32 free_size; /* amount of data left in the block */111 110 uint32 ref_count; /* how many active records are pointing to this 112 111 * block (not used currently) … … 114 113 115 114 uint32 first_hbin_off; /* offset from first hbin block */ 116 uint32 block_size; /* block size of this block is117 * usually a multiple of 4096Kb115 uint32 block_size; /* block size of this block 116 * Should be a multiple of 4096 (0x1000) 118 117 */ 119 uint8 header[HBIN_HDR_SIZE]; /* "hbin" */ 118 uint32 next_block; /* relative offset to next block. Should be 119 * exactly the same as block_size. Stored just 120 * in case this is found to be different in the 121 * future. 122 */ 123 124 uint8 magic[HBIN_MAGIC_SIZE]; /* "hbin" */ 120 125 prs_struct ps; /* data */ 121 bool dirty; /* has this hbin block been modified? */122 126 } REGF_HBIN; 123 127 124 /* ??? List -- list of key offsets and hashed names for consistency */ 125 typedef struct { 128 129 /* Hash List -- list of key offsets and hashed names for consistency */ 130 typedef struct 131 { 126 132 uint32 nk_off; 127 uint8 keycheck[ sizeof(uint32)];133 uint8 keycheck[4]; 128 134 } REGF_HASH_REC; 129 135 130 typedef struct { 136 137 typedef struct 138 { 131 139 REGF_HBIN* hbin; /* pointer to HBIN record (in memory) containing 132 140 * this nk record … … 140 148 } REGF_LF_REC; 141 149 150 142 151 /* Key Value */ 143 144 typedef struct{152 typedef struct 153 { 145 154 REGF_HBIN* hbin; /* pointer to HBIN record (in memory) containing 146 155 * this nk record … … 163 172 struct _regf_sk_rec; 164 173 165 typedef struct _regf_sk_rec { 174 typedef struct _regf_sk_rec 175 { 166 176 struct _regf_sk_rec* next; 167 177 struct _regf_sk_rec* prev; … … 186 196 187 197 /* Key Name */ 188 typedef struct { 198 typedef struct 199 { 189 200 uint32 hbin_off; /* offset from beginning of this hbin block */ 190 201 uint32 rec_size; /* ((start_offset - end_offset) & 0xfffffff8) */ … … 221 232 uint32 num_values; 222 233 uint32 values_off; /* value lists which point to VK records */ 223 uint32 sk_off; /* offset to SK record */ 224 234 uint32 sk_off; /* offset to SK record */ 225 235 } REGF_NK_REC; 226 236 227 237 238 228 239 /* REGF block */ 229 typedef struct { 240 typedef struct 241 { 230 242 /* run time information */ 231 243 int fd; /* file descriptor */ 232 int open_flags; /* flags passed to the open() call */ 244 /* For sanity checking (not part of the registry header) */ 245 uint32 file_length; 233 246 void* mem_ctx; /* memory context for run-time file access information */ 234 247 REGF_HBIN* block_list; /* list of open hbin blocks */ … … 239 252 */ 240 253 241 uint8 header[REGF_HDR_SIZE];/* "regf" */254 uint8 magic[REGF_MAGIC_SIZE];/* "regf" */ 242 255 NTTIME mtime; 243 256 uint32 data_offset; /* offset to record in the first (or any?) … … 245 258 */ 246 259 uint32 last_block; /* offset to last hbin block in file */ 247 uint32 checksum; /* XOR of bytes 0x0000 - 0x01FB */ 248 249 /* unknowns */ 260 261 uint32 checksum; /* Stored checksum. */ 262 uint32 computed_checksum; /* Our own calculation of the checksum. 263 * (XOR of bytes 0x0000 - 0x01FB) 264 */ 265 266 /* unknown data structure values */ 250 267 uint32 unknown1; 251 268 uint32 unknown2; … … 254 271 uint32 unknown5; 255 272 uint32 unknown6; 273 uint32 unknown7; 256 274 } REGF_FILE; 257 275 258 276 259 typedef struct { 277 278 typedef struct 279 { 260 280 REGF_FILE* f; 261 281 void_stack* key_positions; … … 266 286 267 287 268 typedef struct { 288 typedef struct 289 { 269 290 REGF_NK_REC* nk; 270 291 uint32 cur_subkey; … … 316 337 317 338 339 340 /****************/ 341 /* Experimental */ 342 /****************/ 343 typedef struct 344 { 345 uint32 offset; 346 uint32 size; 347 } REGFI_CELL_INFO; 348 349 typedef struct 350 { 351 uint32 count; 352 REGFI_CELL_INFO** cells; 353 } REGFI_CELL_LIST; 354 355 356 REGF_FILE* regfi_parse_regf(int fd, bool strict); 357 REGFI_CELL_LIST* regfi_get_unallocated_cells(REGF_FILE* file); 358 REGF_HBIN* regfi_parse_hbin(REGF_FILE* file, uint32 offset, 359 bool strict, bool save_unalloc); 360 REGF_NK_REC* regfi_parse_nk(REGF_FILE* f, uint32); 361 uint32 regfi_read(int fd, uint8* buf, uint32* length); 362 318 363 #endif /* _REGFI_H */ -
trunk/lib/regfi.c
r95 r97 6 6 * Windows NT registry I/O library 7 7 * 8 * Copyright (C) 2005-200 7Timothy D. Morgan8 * Copyright (C) 2005-2008 Timothy D. Morgan 9 9 * Copyright (C) 2005 Gerald (Jerry) Carter 10 10 * … … 340 340 /******************************************************************* 341 341 *******************************************************************/ 342 static int read_block( REGF_FILE *file, prs_struct *ps, uint32 file_offset,343 uint32 block_size )344 {345 const int hdr_size = 0x20;346 int bytes_read, returned;347 char *buffer;348 SMB_STRUCT_STAT sbuf;349 350 /* check for end of file */351 352 if ( fstat( file->fd, &sbuf ) ) {353 /*DEBUG(0,("read_block: stat() failed! (%s)\n", strerror(errno)));*/354 return -1;355 }356 357 if ( (size_t)file_offset >= sbuf.st_size )358 return -1;359 360 /* if block_size == 0, we are parsnig HBIN records and need361 to read some of the header to get the block_size from there */362 363 if ( block_size == 0 ) {364 uint8 hdr[0x20];365 366 if ( lseek( file->fd, file_offset, SEEK_SET ) == -1 ) {367 /*DEBUG(0,("read_block: lseek() failed! (%s)\n", strerror(errno) ));*/368 return -1;369 }370 371 bytes_read = returned = 0;372 while (bytes_read < hdr_size)373 {374 returned = read(file->fd, hdr + bytes_read, hdr_size - bytes_read);375 if(returned == -1 && errno != EINTR && errno != EAGAIN)376 {377 /*DEBUG(0,("read_block: read of hdr failed (%s)\n",strerror(errno)));*/378 return -1;379 }380 381 if(returned == 0)382 return -1;383 384 bytes_read += returned;385 }386 387 /* make sure this is an hbin header */388 389 if ( strncmp( (char*)hdr, "hbin", HBIN_HDR_SIZE ) != 0 ) {390 /*DEBUG(0,("read_block: invalid block header!\n"));*/391 return -1;392 }393 394 block_size = IVAL( hdr, 0x08 );395 }396 397 /*DEBUG(10,("read_block: block_size == 0x%x\n", block_size ));*/398 399 /* set the offset, initialize the buffer, and read the block from disk */400 401 if ( lseek( file->fd, file_offset, SEEK_SET ) == -1 ) {402 /*DEBUG(0,("read_block: lseek() failed! (%s)\n", strerror(errno) ));*/403 return -1;404 }405 406 prs_init( ps, block_size, file->mem_ctx, UNMARSHALL );407 buffer = ps->data_p;408 bytes_read = returned = 0;409 410 while ( bytes_read < block_size )411 {412 returned = read(file->fd, buffer+bytes_read, block_size-bytes_read);413 if(returned == -1 && errno != EINTR && errno != EAGAIN)414 {415 /*DEBUG(0,("read_block: read() failed (%s)\n", strerror(errno) ));*/416 return -1;417 }418 419 if ((returned == 0) && (bytes_read < block_size))420 {421 /*DEBUG(0,("read_block: not a vald registry file ?\n" ));*/422 return -1;423 }424 425 bytes_read += returned;426 }427 428 return bytes_read;429 }430 431 432 /*******************************************************************433 *******************************************************************/434 static bool prs_regf_block(const char *desc, prs_struct *ps,435 int depth, REGF_FILE *file)436 {437 depth++;438 439 if(!prs_uint8s("header", ps, depth, file->header, sizeof(file->header)))440 return false;441 442 /* yes, these values are always identical so store them only once */443 444 if ( !prs_uint32( "unknown1", ps, depth, &file->unknown1 ))445 return false;446 if ( !prs_uint32( "unknown1 (again)", ps, depth, &file->unknown1 ))447 return false;448 449 /* get the modtime */450 451 if ( !prs_set_offset( ps, 0x0c ) )452 return false;453 if ( !smb_io_time( "modtime", &file->mtime, ps, depth ) )454 return false;455 456 /* constants */457 458 if ( !prs_uint32( "unknown2", ps, depth, &file->unknown2 ))459 return false;460 if ( !prs_uint32( "unknown3", ps, depth, &file->unknown3 ))461 return false;462 if ( !prs_uint32( "unknown4", ps, depth, &file->unknown4 ))463 return false;464 if ( !prs_uint32( "unknown5", ps, depth, &file->unknown5 ))465 return false;466 467 /* get file offsets */468 469 if ( !prs_set_offset( ps, 0x24 ) )470 return false;471 if ( !prs_uint32( "data_offset", ps, depth, &file->data_offset ))472 return false;473 if ( !prs_uint32( "last_block", ps, depth, &file->last_block ))474 return false;475 476 /* one more constant */477 478 if ( !prs_uint32( "unknown6", ps, depth, &file->unknown6 ))479 return false;480 481 /* get the checksum */482 483 if ( !prs_set_offset( ps, 0x01fc ) )484 return false;485 if ( !prs_uint32( "checksum", ps, depth, &file->checksum ))486 return false;487 488 return true;489 }490 491 492 /*******************************************************************493 *******************************************************************/494 static bool prs_hbin_block(const char *desc, prs_struct *ps,495 int depth, REGF_HBIN *hbin)496 {497 uint32 block_size2;498 499 depth++;500 501 if(!prs_uint8s("header", ps, depth, hbin->header, sizeof(hbin->header)))502 return false;503 504 if ( !prs_uint32( "first_hbin_off", ps, depth, &hbin->first_hbin_off ))505 return false;506 507 /* The dosreg.cpp comments say that the block size is at 0x1c.508 According to a WINXP NTUSER.dat file, this is wrong. The block_size509 is at 0x08 */510 511 if ( !prs_uint32( "block_size", ps, depth, &hbin->block_size ))512 return false;513 514 block_size2 = hbin->block_size;515 prs_set_offset( ps, 0x1c );516 if ( !prs_uint32( "block_size2", ps, depth, &block_size2 ))517 return false;518 519 if ( !ps->io )520 hbin->dirty = true;521 522 523 return true;524 }525 526 527 /*******************************************************************528 *******************************************************************/529 342 static bool prs_nk_rec( const char *desc, prs_struct *ps, 530 343 int depth, REGF_NK_REC *nk ) … … 626 439 DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, nk->rec_size));*/ 627 440 628 if ( !ps->io )629 nk->hbin->dirty = true;630 631 441 return true; 632 }633 634 635 /*******************************************************************636 *******************************************************************/637 static uint32 regf_block_checksum( prs_struct *ps )638 {639 char *buffer = ps->data_p;640 uint32 checksum, x;641 int i;642 643 /* XOR of all bytes 0x0000 - 0x01FB */644 645 checksum = x = 0;646 647 for ( i=0; i<0x01FB; i+=4 ) {648 x = IVAL(buffer, i );649 checksum ^= x;650 }651 652 return checksum;653 }654 655 656 /*******************************************************************657 *******************************************************************/658 static bool read_regf_block( REGF_FILE *file )659 {660 prs_struct ps;661 uint32 checksum;662 663 /* grab the first block from the file */664 665 if ( read_block( file, &ps, 0, REGF_BLOCKSIZE ) == -1 )666 return false;667 668 /* parse the block and verify the checksum */669 670 if ( !prs_regf_block( "regf_header", &ps, 0, file ) )671 return false;672 673 checksum = regf_block_checksum( &ps );674 675 if(ps.is_dynamic)676 SAFE_FREE(ps.data_p);677 ps.is_dynamic = false;678 ps.buffer_size = 0;679 ps.data_offset = 0;680 681 if ( file->checksum != checksum ) {682 /*DEBUG(0,("read_regf_block: invalid checksum\n" ));*/683 return false;684 }685 686 return true;687 }688 689 690 /*******************************************************************691 *******************************************************************/692 static REGF_HBIN* read_hbin_block( REGF_FILE *file, off_t offset )693 {694 REGF_HBIN *hbin;695 uint32 record_size, curr_off, block_size, header;696 697 if ( !(hbin = (REGF_HBIN*)zalloc(sizeof(REGF_HBIN))) )698 return NULL;699 hbin->file_off = offset;700 hbin->free_off = -1;701 702 if ( read_block( file, &hbin->ps, offset, 0 ) == -1 )703 return NULL;704 705 if ( !prs_hbin_block( "hbin", &hbin->ps, 0, hbin ) )706 return NULL;707 708 /* this should be the same thing as hbin->block_size but just in case */709 710 block_size = hbin->ps.buffer_size;711 712 /* Find the available free space offset. Always at the end,713 so walk the record list and stop when you get to the end.714 The end is defined by a record header of 0xffffffff. The715 previous 4 bytes contains the amount of free space remaining716 in the hbin block. */717 718 /* remember that the record_size is in the 4 bytes preceeding the record itself */719 720 if ( !prs_set_offset( &hbin->ps, file->data_offset+HBIN_HDR_SIZE-sizeof(uint32) ) )721 return false;722 723 record_size = 0;724 curr_off = hbin->ps.data_offset;725 while ( header != 0xffffffff ) {726 /* not done yet so reset the current offset to the727 next record_size field */728 729 curr_off = curr_off+record_size;730 731 /* for some reason the record_size of the last record in732 an hbin block can extend past the end of the block733 even though the record fits within the remaining734 space....aaarrrgggghhhhhh */735 736 if ( curr_off >= block_size ) {737 record_size = -1;738 curr_off = -1;739 break;740 }741 742 if ( !prs_set_offset( &hbin->ps, curr_off) )743 return false;744 745 if ( !prs_uint32( "rec_size", &hbin->ps, 0, &record_size ) )746 return false;747 if ( !prs_uint32( "header", &hbin->ps, 0, &header ) )748 return false;749 750 assert( record_size != 0 );751 752 if ( record_size & 0x80000000 ) {753 /* absolute_value(record_size) */754 record_size = (record_size ^ 0xffffffff) + 1;755 }756 }757 758 /* save the free space offset */759 760 if ( header == 0xffffffff ) {761 762 /* account for the fact that the curr_off is 4 bytes behind the actual763 record header */764 765 hbin->free_off = curr_off + sizeof(uint32);766 hbin->free_size = record_size;767 }768 769 /*DEBUG(10,("read_hbin_block: free space offset == 0x%x\n", hbin->free_off));*/770 771 if ( !prs_set_offset( &hbin->ps, file->data_offset+HBIN_HDR_SIZE ) )772 return false;773 774 return hbin;775 442 } 776 443 … … 824 491 } 825 492 826 hbin = re ad_hbin_block( file, block_off);493 hbin = regfi_parse_hbin(file, block_off, true, false); 827 494 828 495 if ( hbin ) … … 873 540 /* move to the LF record */ 874 541 875 if ( !prs_set_offset( &hbin->ps, nk->subkeys_off + HBIN_ HDR_SIZE - hbin->first_hbin_off ) )542 if ( !prs_set_offset( &hbin->ps, nk->subkeys_off + HBIN_MAGIC_SIZE - hbin->first_hbin_off ) ) 876 543 return false; 877 544 … … 909 576 /*DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, lf->rec_size));*/ 910 577 911 if ( !hbin->ps.io )912 hbin->dirty = true;913 914 578 return true; 915 579 } … … 927 591 depth++; 928 592 929 if ( !prs_set_offset( &hbin->ps, sk->sk_off + HBIN_ HDR_SIZE - hbin->first_hbin_off ) )593 if ( !prs_set_offset( &hbin->ps, sk->sk_off + HBIN_MAGIC_SIZE - hbin->first_hbin_off ) ) 930 594 return false; 931 595 … … 962 626 /* if ( data_size > sk->rec_size )*/ 963 627 /*DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, sk->rec_size));*/ 964 965 if ( !hbin->ps.io )966 hbin->dirty = true;967 628 968 629 return true; … … 1050 711 if (!(prs_set_offset(&hblock->ps, 1051 712 (vk->data_off 1052 + HBIN_ HDR_SIZE713 + HBIN_MAGIC_SIZE 1053 714 - hblock->first_hbin_off) 1054 715 - sizeof(uint32)))) … … 1066 727 return false; 1067 728 1068 if ( !hblock->ps.io )1069 hblock->dirty = true;1070 729 } 1071 730 else … … 1085 744 DEBUG(10,("prs_vk_rec: data_size check failed (0x%x < 0x%x)\n", data_size, vk->rec_size));*/ 1086 745 1087 if ( !hbin->ps.io )1088 hbin->dirty = true;1089 1090 746 return true; 1091 747 } … … 1118 774 if (!prs_set_offset(&hbin->ps, 1119 775 nk->values_off 1120 + HBIN_ HDR_SIZE776 + HBIN_MAGIC_SIZE 1121 777 - hbin->first_hbin_off 1122 778 - sizeof(uint32))) … … 1155 811 1156 812 new_offset = nk->values[i].rec_off 1157 + HBIN_ HDR_SIZE813 + HBIN_MAGIC_SIZE 1158 814 - sub_hbin->first_hbin_off; 1159 815 … … 1163 819 return false; 1164 820 } 1165 1166 if ( !hbin->ps.io )1167 hbin->dirty = true;1168 821 1169 822 return true; … … 1299 952 curr_off = ps->data_offset; 1300 953 if ( curr_off == 0 ) 1301 prs_set_offset( ps, HBIN_HEADER_REC_SIZE );954 prs_set_offset( ps, HBIN_HEADER_REC_SIZE+4 ); 1302 955 1303 956 /* assume that the current offset is at the reacord header … … 1362 1015 1363 1016 /******************************************************************* 1364 Open the registry file and then read in the REGF block to get the 1365 first hbin offset. 1366 *******************************************************************/ 1367 REGF_FILE* regfi_open( const char *filename ) 1368 { 1369 REGF_FILE *rb; 1017 * Open the registry file and then read in the REGF block to get the 1018 * first hbin offset. 1019 *******************************************************************/ 1020 REGF_FILE* regfi_open(const char* filename) 1021 { 1022 REGF_FILE* rb; 1023 int fd; 1370 1024 int flags = O_RDONLY; 1371 1025 1372 if ( !(rb = (REGF_FILE*)malloc(sizeof(REGF_FILE))) ) { 1373 /* DEBUG(0,("ERROR allocating memory\n")); */ 1374 return NULL; 1375 } 1376 memset(rb, 0, sizeof(REGF_FILE)); 1377 rb->fd = -1; 1378 1379 /* if ( !(rb->mem_ctx = talloc_init( "read_regf_block" )) ) 1380 { 1381 regfi_close( rb ); 1382 return NULL; 1383 } 1384 */ 1385 rb->open_flags = flags; 1386 1387 /* open and existing file */ 1388 1389 if ( (rb->fd = open(filename, flags)) == -1 ) { 1026 /* open an existing file */ 1027 if ((fd = open(filename, flags)) == -1) 1028 { 1390 1029 /* DEBUG(0,("regfi_open: failure to open %s (%s)\n", filename, strerror(errno)));*/ 1391 regfi_close( rb );1392 1030 return NULL; 1393 1031 } 1394 1032 1395 1033 /* read in an existing file */ 1396 1397 if ( !read_regf_block( rb ) ){1034 if ((rb = regfi_parse_regf(fd, true)) == NULL) 1035 { 1398 1036 /* DEBUG(0,("regfi_open: Failed to read initial REGF block\n"));*/ 1399 regfi_close( rb);1037 close(fd); 1400 1038 return NULL; 1401 1039 } 1402 1040 1403 1041 /* success */ 1404 1405 1042 return rb; 1406 1043 } … … 1466 1103 block (but I'm not assuming that for now) */ 1467 1104 1468 while ( (hbin = re ad_hbin_block( file, offset)) ) {1105 while ( (hbin = regfi_parse_hbin(file, offset, true, false)) ) { 1469 1106 eob = false; 1470 1107 … … 1754 1391 1755 1392 if(!prs_set_offset(&hbin->ps, 1756 HBIN_ HDR_SIZE + nk_offset - hbin->first_hbin_off))1393 HBIN_MAGIC_SIZE + nk_offset - hbin->first_hbin_off)) 1757 1394 return NULL; 1758 1395 … … 1848 1485 return ret_val; 1849 1486 } 1487 1488 1489 1490 /****************/ 1491 /* Experimental */ 1492 /****************/ 1493 /* 1494 typedef struct { 1495 uint32 offset; 1496 uint32 size; 1497 } REGFI_CELL_INFO; 1498 1499 typedef struct { 1500 uint32 count 1501 REGFI_CELL_INFO** cells; 1502 } REGFI_CELL_LIST; 1503 */ 1504 1505 1506 /******************************************************************* 1507 * Computes the checksum of the registry file header. 1508 * buffer must be at least the size of an regf header (4096 bytes). 1509 *******************************************************************/ 1510 static uint32 regfi_compute_header_checksum(uint8* buffer) 1511 { 1512 uint32 checksum, x; 1513 int i; 1514 1515 /* XOR of all bytes 0x0000 - 0x01FB */ 1516 1517 checksum = x = 0; 1518 1519 for ( i=0; i<0x01FB; i+=4 ) { 1520 x = IVAL(buffer, i ); 1521 checksum ^= x; 1522 } 1523 1524 return checksum; 1525 } 1526 1527 1528 /******************************************************************* 1529 * TODO: add way to return more detailed error information. 1530 *******************************************************************/ 1531 REGF_FILE* regfi_parse_regf(int fd, bool strict) 1532 { 1533 uint8 file_header[REGF_BLOCKSIZE]; 1534 uint32 ret, length; 1535 uint32 file_length; 1536 struct stat sbuf; 1537 REGF_FILE* ret_val; 1538 1539 /* Determine file length. Must be at least big enough 1540 * for the header and one hbin. 1541 */ 1542 if (fstat(fd, &sbuf) == -1) 1543 return NULL; 1544 file_length = sbuf.st_size; 1545 if(file_length < REGF_BLOCKSIZE+REGF_ALLOC_BLOCK) 1546 return NULL; 1547 1548 ret_val = (REGF_FILE*)zalloc(sizeof(REGF_FILE)); 1549 if(ret_val == NULL) 1550 return NULL; 1551 1552 ret_val->fd = fd; 1553 ret_val->file_length = file_length; 1554 1555 length = REGF_BLOCKSIZE; 1556 if((ret = regfi_read(fd, file_header, &length)) != 0 1557 || length != REGF_BLOCKSIZE) 1558 { 1559 free(ret_val); 1560 return NULL; 1561 } 1562 1563 ret_val->checksum = IVAL(file_header, 0x1FC); 1564 ret_val->computed_checksum = regfi_compute_header_checksum(file_header); 1565 if (strict && (ret_val->checksum != ret_val->computed_checksum)) 1566 { 1567 free(ret_val); 1568 return NULL; 1569 } 1570 1571 memcpy(ret_val->magic, file_header, 4); 1572 if(strict && (memcmp(ret_val->magic, "regf", 4) != 0)) 1573 { 1574 free(ret_val); 1575 return NULL; 1576 } 1577 1578 ret_val->unknown1 = IVAL(file_header, 0x4); 1579 ret_val->unknown2 = IVAL(file_header, 0x8); 1580 1581 ret_val->mtime.low = IVAL(file_header, 0xC); 1582 ret_val->mtime.high = IVAL(file_header, 0x10); 1583 1584 ret_val->unknown3 = IVAL(file_header, 0x14); 1585 ret_val->unknown4 = IVAL(file_header, 0x18); 1586 ret_val->unknown5 = IVAL(file_header, 0x1C); 1587 ret_val->unknown6 = IVAL(file_header, 0x20); 1588 1589 ret_val->data_offset = IVAL(file_header, 0x24); 1590 ret_val->last_block = IVAL(file_header, 0x28); 1591 1592 ret_val->unknown7 = IVAL(file_header, 0x2C); 1593 1594 return ret_val; 1595 } 1596 1597 1598 1599 /******************************************************************* 1600 * Given real file offset, read and parse the hbin at that location 1601 * along with it's associated cells. If save_unalloc is true, a list 1602 * of unallocated cell offsets will be stored in TODO. 1603 *******************************************************************/ 1604 /* TODO: Need a way to return types of errors. Also need to free 1605 * the hbin/ps when an error occurs. 1606 */ 1607 REGF_HBIN* regfi_parse_hbin(REGF_FILE* file, uint32 offset, 1608 bool strict, bool save_unalloc) 1609 { 1610 REGF_HBIN *hbin; 1611 uint8 hbin_header[HBIN_HEADER_REC_SIZE]; 1612 uint32 length, curr_off; 1613 int32 cell_len; 1614 bool is_unalloc; 1615 1616 if(!(hbin = (REGF_HBIN*)zalloc(sizeof(REGF_HBIN)))) 1617 return NULL; 1618 hbin->file_off = offset; 1619 1620 if(lseek(file->fd, offset, SEEK_SET) == -1) 1621 return NULL; 1622 1623 length = HBIN_HEADER_REC_SIZE; 1624 if((regfi_read(file->fd, hbin_header, &length) != 0) 1625 || length != HBIN_HEADER_REC_SIZE) 1626 return NULL; 1627 1628 if(lseek(file->fd, offset, SEEK_SET) == -1) 1629 return NULL; 1630 1631 memcpy(hbin->magic, hbin_header, 4); 1632 if(strict && (memcmp(hbin->magic, "hbin", 4) != 0)) 1633 return NULL; 1634 1635 hbin->first_hbin_off = IVAL(hbin_header, 0x4); 1636 hbin->block_size = IVAL(hbin_header, 0x8); 1637 /* this should be the same thing as hbin->block_size but just in case */ 1638 hbin->next_block = IVAL(hbin_header, 0x1C); 1639 1640 1641 /* TODO: This check is this more of a way to determine if they are ever 1642 * not the same than to really do sanity checking. This may need 1643 * to be changed or removed once these fields are better understood. */ 1644 if(strict && (hbin->block_size != hbin->next_block)) 1645 { 1646 fprintf(stderr, "DEBUG: hbin->block_size != hbin->next_block\n"); 1647 return NULL; 1648 } 1649 1650 1651 /* Ensure the block size is a multiple of 0x1000 and doesn't run off 1652 * the end of the file. 1653 */ 1654 /* TODO: This may need to be relaxed for dealing with 1655 * partial or corrupt files. */ 1656 if((offset + hbin->block_size > file->file_length) 1657 || (hbin->block_size & 0xFFFFF000) != hbin->block_size) 1658 return NULL; 1659 1660 1661 /* TODO: need to get rid of this, but currently lots depends on the 1662 * ps structure. 1663 */ 1664 if(!prs_init(&hbin->ps, hbin->block_size, file->mem_ctx, UNMARSHALL)) 1665 return NULL; 1666 length = hbin->block_size; 1667 if((regfi_read(file->fd, (uint8*)hbin->ps.data_p, &length) != 0) 1668 || length != hbin->block_size) 1669 return NULL; 1670 1671 1672 if(save_unalloc) 1673 { 1674 is_unalloc = false; 1675 cell_len = 0; 1676 curr_off = HBIN_HEADER_REC_SIZE; 1677 while ( curr_off < hbin->block_size ) 1678 { 1679 cell_len = IVALS(hbin->ps.data_p, curr_off); 1680 1681 if(cell_len > 0) 1682 is_unalloc = true; 1683 else 1684 cell_len = -1*cell_len; 1685 1686 if((cell_len == 0) || ((cell_len & 0xFFFFFFFC) != cell_len)) 1687 /* TODO: should report an error here. */ 1688 break; 1689 1690 /* for some reason the record_size of the last record in 1691 an hbin block can extend past the end of the block 1692 even though the record fits within the remaining 1693 space....aaarrrgggghhhhhh */ 1694 if(curr_off + cell_len >= hbin->block_size) 1695 cell_len = hbin->block_size - curr_off; 1696 1697 if(is_unalloc) 1698 /* TODO: save cell info */ 1699 1700 curr_off = curr_off+cell_len; 1701 } 1702 } 1703 1704 /* TODO: need to get rid of this, but currently lots depends on the 1705 * ps structure. 1706 */ 1707 if(!prs_set_offset(&hbin->ps, file->data_offset+HBIN_MAGIC_SIZE)) 1708 return NULL; 1709 1710 return hbin; 1711 } 1712 1713 1714 /***************************************************************************** 1715 * This function is just like read(2), except that it continues to 1716 * re-try reading from the file descriptor if EINTR or EAGAIN is received. 1717 * regfi_read will attempt to read length bytes from fd and write them to buf. 1718 * 1719 * On success, 0 is returned. Upon failure, an errno code is returned. 1720 * 1721 * The number of bytes successfully read is returned through the length 1722 * parameter by reference. If both the return value and length parameter are 1723 * returned as 0, then EOF was encountered immediately 1724 *****************************************************************************/ 1725 uint32 regfi_read(int fd, uint8* buf, uint32* length) 1726 { 1727 uint32 rsize = 0; 1728 uint32 rret = 0; 1729 1730 do 1731 { 1732 rret = read(fd, buf + rsize, *length - rsize); 1733 if(rret > 0) 1734 rsize += rret; 1735 }while(*length - rsize > 0 1736 && (rret > 0 || (rret == -1 && (errno == EAGAIN || errno == EINTR)))); 1737 1738 *length = rsize; 1739 if (rret == -1 && errno != EINTR && errno != EAGAIN) 1740 return errno; 1741 1742 return 0; 1743 } -
trunk/src/reglookup.c
r93 r97 754 754 755 755 756 /* XXX: what if there is BOTH a value AND a key with that name?? */ 756 757 /* 757 758 * Returns 0 if path was not found.
Note: See TracChangeset
for help on using the changeset viewer.