/* Definitions for the REGF registry file format as used by Windows NT4 and above. Written by Jelmer Vernooij, 2005 Based on two files from Samba 3: regedit.c by Richard Sharpe regfio.c by Jerry Carter Thanks to Wilco Baan Hofman for some of the info on li and ri fields. */ interface regf { const int REGF_OFFSET_NONE = 0xffffffff; /* * Registry version number * 1.3.0.1 for WinNT 4 * 1.5.0.1 for WinXP */ typedef [noprint] struct { [value(1)] uint32 major; [value(3)] uint32 minor; [value(0)] uint32 release; [value(1)] uint32 build; } regf_version; /* "regf" is obviously the abbreviation for "Registry file". "regf" is the signature of the header-block which is always 4kb in size, although only the first 64 bytes seem to be used and a checksum is calculated over the first 0x200 bytes only! */ typedef [public,noprint] struct { [charset(DOS)] uint8 REGF_ID[4]; /* 'regf' */ uint32 update_counter1; uint32 update_counter2; NTTIME modtime; regf_version version; uint32 data_offset; uint32 last_block; [value(1)] uint32 uk7; /* 1 */ [charset(UTF16)] uint16 description[0x40]; uint32 padding[83]; /* Padding */ /* Checksum of first 0x200 bytes XOR-ed */ uint32 chksum; } regf_hdr; /* hbin probably means hive-bin (what bin stands for I don't know) This block is always a multiple of 4kb in size. */ typedef [public,noprint] struct { [charset(DOS)] uint8 HBIN_ID[4]; /* hbin */ uint32 offset_from_first; /* Offset from 1st hbin-Block */ uint32 offset_to_next; /* Offset to the next hbin-Block */ uint32 unknown[2]; NTTIME last_change; uint32 block_size; /* Block size (including the header!) */ uint8 data[offset_to_next-0x20]; /* data is filled with: uint32 length; Negative if in used, positive otherwise Always a multiple of 8 uint8_t data[length]; Free space marker if 0xffffffff */ } hbin_block; typedef [base_type(uint16),noprint] enum { REG_ROOT_KEY = 0x20, REG_SUB_KEY = 0x2C, REG_SYM_LINK = 0x10 } reg_key_type; /* The nk-record can be treated as a combination of tree-record and key-record of the win 95 registry. */ typedef [public,noprint] struct { [charset(DOS)] uint8 header[2]; reg_key_type type; NTTIME last_change; uint32 uk1; uint32 parent_offset; uint32 num_subkeys; uint32 uk2; uint32 subkeys_offset; uint32 unknown_offset; uint32 num_values; uint32 values_offset; /* Points to a list of offsets of vk-records */ uint32 sk_offset; uint32 clsname_offset; uint32 unk3[5]; [value(strlen(key_name))] uint16 name_length; uint16 clsname_length; [charset(DOS)] uint8 key_name[name_length]; } nk_block; /* sk (? Security Key ?) is the ACL of the registry. */ typedef [noprint,public] struct { [charset(DOS)] uint8 header[2]; uint16 tag; uint32 prev_offset; uint32 next_offset; uint32 ref_cnt; uint32 rec_size; uint8 sec_desc[rec_size]; } sk_block; typedef [noprint,nopush,nopull] struct { uint32 offset_nk; uint32 base37; /* base37 of key name */ } lh_hash; /* Subkey listing with hash of first 4 characters */ typedef [noprint,nopush,nopull] struct { [charset(DOS)] uint8 header[2]; uint16 key_count; lh_hash hashes[key_count]; } lh_block; typedef [noprint,nopush,nopull] struct { [charset(DOS)] uint8 header[2]; uint16 key_count; uint32 offset_nk[key_count]; } li_block; typedef [noprint,nopush,nopull] struct { [charset(DOS)] uint8 header[2]; uint16 key_count; uint32 offset[key_count]; /* li/lh offset */ } ri_block; /* The vk-record consists information to a single value (value key). */ typedef [public,noprint] struct { [charset(DOS)] uint8 header[2]; [value(strlen(data_name))] uint16 name_length; uint32 data_length; /* If top-bit set, offset contains the data */ uint32 data_offset; uint32 data_type; uint16 flag; /* =1, has name, else no name (=Default). */ uint16 unk1; [charset(DOS)] uint8 data_name[name_length]; } vk_block; typedef [noprint] struct { uint32 nk_off; [charset(DOS)] uint8 hash[4]; } hash_record; /* The lf-record is the counterpart to the RGKN-record (the hash-function) */ typedef [public,noprint] struct { [charset(DOS)] uint8 header[2]; uint16 key_count; hash_record hr[key_count]; /* Array of hash records, depending on key_count */ } lf_block; }