svn commit: samba r15458 - in branches/SAMBA_4_0/source/lib/registry: .

jelmer at samba.org jelmer at samba.org
Fri May 5 13:16:58 GMT 2006


Author: jelmer
Date: 2006-05-05 13:16:58 +0000 (Fri, 05 May 2006)
New Revision: 15458

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=15458

Log:
Fix support for Windows XP-style registry files and support for large numbers of subkeys.

Patch by Wilco Baan Hofman <wilco at baanhofman.nl>

Modified:
   branches/SAMBA_4_0/source/lib/registry/reg_backend_nt4.c
   branches/SAMBA_4_0/source/lib/registry/regf.idl


Changeset:
Modified: branches/SAMBA_4_0/source/lib/registry/reg_backend_nt4.c
===================================================================
--- branches/SAMBA_4_0/source/lib/registry/reg_backend_nt4.c	2006-05-05 13:02:14 UTC (rev 15457)
+++ branches/SAMBA_4_0/source/lib/registry/reg_backend_nt4.c	2006-05-05 13:16:58 UTC (rev 15458)
@@ -2,6 +2,7 @@
    Samba CIFS implementation
    Registry backend for REGF files
    Copyright (C) 2005 Jelmer Vernooij, jelmer at samba.org
+   Copyright (C) 2006 Wilco Baan Hofman, wilco at baanhofman.nl
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -484,8 +485,25 @@
 	}
 
 	if (!strncmp((char *)data.data, "li", 2)) {
-		DEBUG(4, ("Subkeys in LI list\n"));
-		SMB_ASSERT(0);
+		struct li_block li;
+		struct tdr_pull pull;
+
+		DEBUG(10, ("Subkeys in LI list\n"));
+		ZERO_STRUCT(pull);
+		pull.data = data;
+
+		if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) {
+			DEBUG(0, ("Error parsing LI list\n"));
+			return WERR_GENERAL_FAILURE;
+		}
+		SMB_ASSERT(!strncmp(li.header, "li",2));
+
+		if (li.key_count != nk->num_subkeys) {
+			DEBUG(0, ("Subkey counts don't match\n"));
+			return WERR_GENERAL_FAILURE;
+		}
+		key_off = li.nk_offset[idx];
+	
 	} else if (!strncmp((char *)data.data, "lf", 2)) {
 		struct lf_block lf;
 		struct tdr_pull pull;
@@ -498,19 +516,107 @@
 			DEBUG(0, ("Error parsing LF list\n"));
 			return WERR_GENERAL_FAILURE;
 		}
+		SMB_ASSERT(!strncmp(lf.header, "lf",2));
 
 		if (lf.key_count != nk->num_subkeys) {
 			DEBUG(0, ("Subkey counts don't match\n"));
 			return WERR_GENERAL_FAILURE;
 		}
 
-		key_off = lf.hr[idx].nk_off;
+		key_off = lf.hr[idx].nk_offset;
+	} else if (!strncmp((char *)data.data, "lh", 2)) {
+		struct lh_block lh;
+		struct tdr_pull pull;
+		
+		DEBUG(10, ("Subkeys in LH list"));
+		ZERO_STRUCT(pull);
+		pull.data = data;
+		
+		if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) {
+			DEBUG(0, ("Error parsing LH list\n"));
+			return WERR_GENERAL_FAILURE;
+		}
+		SMB_ASSERT(!strncmp(lh.header, "lh",2));
+		
+		if (lh.key_count != nk->num_subkeys) {
+			DEBUG(0, ("Subkey counts don't match\n"));
+			return WERR_GENERAL_FAILURE;
+		}
+		key_off = lh.hr[idx].nk_offset;
 	} else if (!strncmp((char *)data.data, "ri", 2)) {
-		DEBUG(4, ("Subkeys in RI list\n"));
-		SMB_ASSERT(0);
-	} else if (!strncmp((char *)data.data, "lh", 2)) {
-		DEBUG(4, ("Subkeys in LH list\n"));
-		SMB_ASSERT(0);
+		struct ri_block ri;
+		struct tdr_pull pull;
+		uint16_t i;
+		uint16_t sublist_count = 0;
+		
+		ZERO_STRUCT(pull);
+		pull.data = data;
+		
+		if (NT_STATUS_IS_ERR(tdr_pull_ri_block(&pull, nk, &ri))) {
+			DEBUG(0, ("Error parsing RI list\n"));
+			return WERR_GENERAL_FAILURE;
+		}
+		SMB_ASSERT(!strncmp(ri.header, "ri",2));
+		
+		for (i = 0; i < ri.key_count; i++) {
+			DATA_BLOB list_data;
+			
+			/* Get sublist data blob */
+			list_data = hbin_get(key->hive->backend_data, ri.offset[i]);
+			if (!list_data.data) {
+				DEBUG(0, ("Error getting RI list."));
+				return WERR_GENERAL_FAILURE;
+			}
+			
+			ZERO_STRUCT(pull);
+			pull.data = list_data;
+			
+			if (!strncmp((char *)list_data.data, "li", 2)) {
+				struct li_block li;
+
+				if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) {
+					DEBUG(0, ("Error parsing LI list from RI\n"));
+					return WERR_GENERAL_FAILURE;
+				}
+				SMB_ASSERT(!strncmp(li.header, "li",2));
+				
+				/* Advance to next sublist if necessary */
+				if (idx >= sublist_count + li.key_count) {
+					sublist_count += li.key_count;
+					continue;
+				}
+				key_off = li.nk_offset[idx - sublist_count];
+				sublist_count += li.key_count;
+				break;
+			} else if (!strncmp((char *)list_data.data, "lh", 2)) {
+				struct lh_block lh;
+				
+				if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) {
+					DEBUG(0, ("Error parsing LH list from RI\n"));
+					return WERR_GENERAL_FAILURE;
+				}
+				SMB_ASSERT(!strncmp(lh.header, "lh",2));
+
+				
+				/* Advance to next sublist if necessary */
+				if (idx >= sublist_count + lh.key_count) {
+					sublist_count += lh.key_count;
+					continue;
+				}
+				key_off = lh.hr[idx - sublist_count].nk_offset;
+				sublist_count += lh.key_count;
+				break;
+			} else {
+				DEBUG(0,("Unknown sublist in ri block\n"));
+				SMB_ASSERT(0);
+			}
+			
+		}
+	
+		if (idx > sublist_count) {
+			return WERR_NO_MORE_ITEMS;
+		}
+
 	} else {
 		DEBUG(0, ("Unknown type for subkey list (0x%04x): %c%c\n", nk->subkeys_offset, data.data[0], data.data[1]));
 		return WERR_GENERAL_FAILURE;
@@ -577,7 +683,7 @@
 	}
 
 	lf.hr = talloc_realloc(regf, lf.hr, struct hash_record, lf.key_count+1);
-	lf.hr[lf.key_count].nk_off = key_offset;
+	lf.hr[lf.key_count].nk_offset = key_offset;
 	lf.hr[lf.key_count].hash = talloc_strndup(regf, name, 4);
 	lf.key_count++;
 
@@ -736,7 +842,7 @@
 	regf->hbins = talloc_array(regf, struct hbin_block *, 1);
 	regf->hbins[0] = NULL;
 
-	while (pull.offset < pull.data.length) {
+	while (pull.offset < pull.data.length && pull.offset < regf->header->last_block) {
 		struct hbin_block *hbin = talloc(regf->hbins, struct hbin_block);
 
 		if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(&pull, hbin, hbin))) {

Modified: branches/SAMBA_4_0/source/lib/registry/regf.idl
===================================================================
--- branches/SAMBA_4_0/source/lib/registry/regf.idl	2006-05-05 13:02:14 UTC (rev 15457)
+++ branches/SAMBA_4_0/source/lib/registry/regf.idl	2006-05-05 13:16:58 UTC (rev 15458)
@@ -2,13 +2,13 @@
  Definitions for the REGF registry file format as used by 
  Windows NT4 and above. 
 
- Written by Jelmer Vernooij, 2005
+   Copyright (C) 2005 Jelmer Vernooij, jelmer at samba.org
+   Copyright (C) 2006 Wilco Baan Hofman, wilco at baanhofman.nl
    
  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
@@ -114,25 +114,25 @@
 		uint8 sec_desc[rec_size]; 
 	} sk_block;
 
-	typedef [noprint,nopush,nopull] struct {
-			uint32 offset_nk;
+	typedef [noprint] struct {
+			uint32 nk_offset;
 			uint32 base37; /* base37 of key name */
 	} lh_hash;
 	
 	/* Subkey listing with hash of first 4 characters */
-	typedef [noprint,nopush,nopull] struct {
+	typedef [public,noprint] struct {
 		[charset(DOS)] uint8 header[2];
 		uint16 key_count;
-		lh_hash hashes[key_count];
+		lh_hash hr[key_count];
 	} lh_block;
 
-	typedef [noprint,nopush,nopull] struct {
+	typedef [public,noprint] struct {
 		[charset(DOS)] uint8 header[2];
 		uint16 key_count;
-		uint32 offset_nk[key_count];
+		uint32 nk_offset[key_count];
 	} li_block;
 
-	typedef [noprint,nopush,nopull] struct {
+	typedef [public,noprint] struct {
 		[charset(DOS)] uint8 header[2];
 		uint16 key_count;
 		uint32 offset[key_count]; /* li/lh offset */
@@ -151,7 +151,7 @@
 	} vk_block;
 
 	typedef [noprint] struct {
-		uint32 nk_off;
+		uint32 nk_offset;
 		[charset(DOS)] uint8 hash[4];
 	} hash_record;
 



More information about the samba-cvs mailing list