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

jelmer at samba.org jelmer at samba.org
Wed May 17 13:58:53 GMT 2006


Author: jelmer
Date: 2006-05-17 13:58:53 +0000 (Wed, 17 May 2006)
New Revision: 15659

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

Log:
Implement opening a key by name (significant better performance 
in some situations). Patch by Wilco Baan Hofman.

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


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-17 12:59:30 UTC (rev 15658)
+++ branches/SAMBA_4_0/source/lib/registry/reg_backend_nt4.c	2006-05-17 13:58:53 UTC (rev 15659)
@@ -469,7 +469,7 @@
 	return WERR_OK;
 }
 
-static WERROR regf_get_subkey (TALLOC_CTX *ctx, const struct registry_key *key, int idx, struct registry_key **ret)
+static WERROR regf_get_subkey_by_index (TALLOC_CTX *ctx, const struct registry_key *key, int idx, struct registry_key **ret)
 {
 	DATA_BLOB data;
 	struct nk_block *nk = key->backend_data;
@@ -627,7 +627,240 @@
 	return WERR_OK;
 }
 
+static WERROR regf_match_subkey_by_name (TALLOC_CTX *ctx, const struct registry_key *key, uint32_t offset, const char *name, uint32_t *ret) 
+{
+	DATA_BLOB subkey_data;
+	struct nk_block subkey;
+	struct tdr_pull pull;
+	
+	subkey_data = hbin_get(key->hive->backend_data, offset);
+	if (!subkey_data.data) {
+		DEBUG(0, ("Unable to retrieve subkey HBIN\n"));
+		return WERR_GENERAL_FAILURE;
+	}
 
+	ZERO_STRUCT(pull);
+	pull.data = subkey_data;
+	
+	if (NT_STATUS_IS_ERR(tdr_pull_nk_block(&pull, ctx, &subkey))) {
+		DEBUG(0, ("Error parsing NK structure.\n"));
+		return WERR_GENERAL_FAILURE;
+	}
+	if (strncmp(subkey.header, "nk", 2)) {
+		DEBUG(0, ("Not an NK structure.\n"));
+		return WERR_GENERAL_FAILURE;
+	}
+	if (!strcasecmp(subkey.key_name, name)) {
+		*ret = offset;
+	} else {
+		*ret = 0;
+	}
+	return WERR_OK;
+}
+	
+static WERROR regf_get_subkey_by_name (TALLOC_CTX *ctx, const struct registry_key *key, const char *name, struct registry_key **ret)
+{
+	DATA_BLOB data;
+	struct nk_block *nk = key->backend_data;
+	uint32_t key_off = 0;
+
+	data = hbin_get(key->hive->backend_data, nk->subkeys_offset);
+	if (!data.data) {
+		DEBUG(0, ("Unable to find subkey list\n"));
+		return WERR_GENERAL_FAILURE;
+	}
+
+	if (!strncmp((char *)data.data, "li",2)) {
+		struct li_block li;
+		struct tdr_pull pull;
+		uint16_t i;
+
+		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;
+		}
+		
+		for (i = 0; i < li.key_count; i++) {
+			W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, li.nk_offset[i], name, &key_off));
+			if (key_off) {
+				break;
+			}
+		}
+		if (!key_off) {
+			return WERR_DEST_NOT_FOUND;
+		}
+	} else if (!strncmp((char *)data.data, "lf",2)) {
+		struct lf_block lf;
+		struct tdr_pull pull;
+		uint16_t i;
+
+		DEBUG(10, ("Subkeys in LF list\n"));
+		ZERO_STRUCT(pull);
+		pull.data = data;
+		
+		if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, nk, &lf))) {
+			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;
+		}
+		
+		for (i = 0; i < lf.key_count; i++) {
+			if (strncmp(lf.hr[i].hash, name, 4)) {
+				continue;
+			}
+			W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, lf.hr[i].nk_offset, name, &key_off));
+			if (key_off) {
+				break;
+			}
+		}
+		if (!key_off) {
+			return WERR_DEST_NOT_FOUND;
+		}
+	} else if (!strncmp((char *)data.data, "lh",2)) {
+		struct lh_block lh;
+		struct tdr_pull pull;
+		uint16_t i;
+		uint32_t hash = 0;
+		char *hash_name;
+
+		DEBUG(10, ("Subkeys in LH list\n"));
+		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;
+		}
+		
+		/* Compute hash for the name */
+		hash_name = strupper_talloc(nk, name);		
+		for (i = 0; *(hash_name + i) != 0; i++) {
+			hash *= 37;
+			hash += *(hash_name + i);
+		}
+		for (i = 0; i < lh.key_count; i++) {
+			if (lh.hr[i].base37 != hash) {
+				continue;
+			}
+			W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, lh.hr[i].nk_offset, name, &key_off));
+			if (key_off) {
+				break;
+			}
+		}	
+		if (!key_off) {
+			return WERR_DEST_NOT_FOUND;
+		}
+	} else if (!strncmp((char *)data.data, "ri", 2)) {
+		struct ri_block ri;
+		struct tdr_pull pull;
+		uint16_t i, j;
+
+		DEBUG(10, ("Subkeys in RI list\n"));
+		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));
+				
+				for (j = 0; j < li.key_count; j++) {
+					W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, 
+								li.nk_offset[j], name, &key_off));
+					if (key_off) {
+						break;
+					}
+				}
+			} else if (!strncmp((char *)list_data.data, "lh", 2)) {
+				struct lh_block lh;
+				uint32_t hash = 0;
+				char *hash_name;
+				
+				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));
+
+				/* Compute hash for the name */
+				hash_name = strupper_talloc(nk, name);		
+				for (j = 0; *(hash_name + j) != 0; j++) {
+					hash *= 37;
+					hash += *(hash_name + j);
+				}
+				for (j = 0; j < lh.key_count; j++) {
+					if (lh.hr[j].base37 != hash) {
+						continue;
+					}
+					W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, 
+								lh.hr[j].nk_offset, name, &key_off));
+					if (key_off) {
+						break;
+					}
+				}
+			}
+			if (key_off) {
+				break;
+			}
+				
+		}
+		if (!key_off) {
+			return WERR_DEST_NOT_FOUND;
+		}
+	} else {
+		DEBUG(0, ("Unknown subkey list type.\n"));
+		return WERR_GENERAL_FAILURE;
+	}
+
+	*ret = regf_get_key (ctx, key->hive->backend_data, key_off);
+	return WERR_OK;
+}
+
 static WERROR regf_set_sec_desc (const struct registry_key *key, const struct security_descriptor *sec_desc)
 {
 	/* FIXME */
@@ -873,7 +1106,8 @@
 	.open_hive = nt_open_hive,
 	.num_subkeys = regf_num_subkeys,
 	.num_values = regf_num_values,
-	.get_subkey_by_index = regf_get_subkey,
+	.get_subkey_by_index = regf_get_subkey_by_index,
+	.get_subkey_by_name = regf_get_subkey_by_name,
 	.get_value_by_index = regf_get_value,
 	.key_get_sec_desc = regf_get_sec_desc,
 	.key_set_sec_desc = regf_set_sec_desc,



More information about the samba-cvs mailing list