⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 patchfile.c

📁 samba最新软件
💻 C
字号:
/*   Unix SMB/CIFS implementation.   Reading registry patch files   Copyright (C) Jelmer Vernooij 2004-2007   Copyright (C) Wilco Baan Hofman 2006   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   the Free Software Foundation; either version 3 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program.  If not, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "lib/registry/registry.h"#include "system/filesys.h"#include "param/param.h"_PUBLIC_ WERROR reg_preg_diff_load(int fd,				   struct smb_iconv_convenience *iconv_convenience, 				   const struct reg_diff_callbacks *callbacks,				   void *callback_data);_PUBLIC_ WERROR reg_dotreg_diff_load(int fd,				     struct smb_iconv_convenience *iconv_convenience,				     const struct reg_diff_callbacks *callbacks,				     void *callback_data);/* * Generate difference between two keys */WERROR reg_generate_diff_key(struct registry_key *oldkey,			     struct registry_key *newkey,			     const char *path,			     const struct reg_diff_callbacks *callbacks,			     void *callback_data){	int i;	struct registry_key *t1 = NULL, *t2 = NULL;	char *tmppath;	const char *keyname1;	WERROR error, error1, error2;	TALLOC_CTX *mem_ctx = talloc_init("writediff");	uint32_t old_num_subkeys, old_num_values,			 new_num_subkeys, new_num_values;	if (oldkey != NULL) {		error = reg_key_get_info(mem_ctx, oldkey, NULL,					 &old_num_subkeys, &old_num_values,					 NULL, NULL, NULL, NULL);		if (!W_ERROR_IS_OK(error)) {			DEBUG(0, ("Error occured while getting key info: %s\n",				win_errstr(error)));			return error;		}	} else {		old_num_subkeys = 0;		old_num_values = 0;	}	/* Subkeys that were deleted */	for (i = 0; i < old_num_subkeys; i++) {		error1 = reg_key_get_subkey_by_index(mem_ctx, oldkey, i,						     &keyname1,						     NULL, NULL);		if (!W_ERROR_IS_OK(error1)) {			DEBUG(0, ("Error occured while getting subkey by index: %s\n",				win_errstr(error2)));			continue;		}		if (newkey != NULL) {			error2 = reg_open_key(mem_ctx, newkey, keyname1, &t2);			if (W_ERROR_IS_OK(error2))				continue;		} else {			error2 = WERR_BADFILE;			t2 = NULL;		}		if (!W_ERROR_EQUAL(error2, WERR_BADFILE)) {			DEBUG(0, ("Error occured while getting subkey by name: %s\n",				win_errstr(error2)));			talloc_free(mem_ctx);			return error2;		}		/* newkey didn't have such a subkey, add del diff */		tmppath = talloc_asprintf(mem_ctx, "%s\\%s", path, keyname1);		callbacks->del_key(callback_data, tmppath);		talloc_free(tmppath);	}	if (newkey != NULL) {		error = reg_key_get_info(mem_ctx, newkey, NULL,					 &new_num_subkeys, &new_num_values,					 NULL, NULL, NULL, NULL);		if (!W_ERROR_IS_OK(error)) {			DEBUG(0, ("Error occured while getting key info: %s\n",				win_errstr(error)));			return error;		}	} else {		new_num_subkeys = 0;		new_num_values = 0;	}	/* Subkeys that were added */	for(i = 0; i < new_num_subkeys; i++) {		error1 = reg_key_get_subkey_by_index(mem_ctx, newkey,						     i, &keyname1,						     NULL, NULL);		if (!W_ERROR_IS_OK(error1)) {			DEBUG(0, ("Error occured while getting subkey by index: %s\n",				win_errstr(error1)));			talloc_free(mem_ctx);			return error1;		}		if (oldkey != NULL) {			error2 = reg_open_key(mem_ctx, oldkey, keyname1, &t1);			if (W_ERROR_IS_OK(error2))				continue;		} else {			t1 = NULL;			error2 = WERR_BADFILE;		}		if (!W_ERROR_EQUAL(error2, WERR_BADFILE)) {			DEBUG(0, ("Error occured while getting subkey by name: %s\n",				win_errstr(error2)));			talloc_free(mem_ctx);			return error2;		}		/* oldkey didn't have such a subkey, add add diff */		tmppath = talloc_asprintf(mem_ctx, "%s\\%s", path, keyname1);		callbacks->add_key(callback_data, tmppath);		W_ERROR_NOT_OK_RETURN(				reg_open_key(mem_ctx, newkey, keyname1, &t2));		reg_generate_diff_key(t1, t2, tmppath,				      callbacks, callback_data);		talloc_free(tmppath);	}	/* Values that were changed */	for(i = 0; i < new_num_values; i++) {		const char *name;		uint32_t type1, type2;		DATA_BLOB contents1, contents2;		error1 = reg_key_get_value_by_index(mem_ctx, newkey, i,						    &name, &type1, &contents1);		if (!W_ERROR_IS_OK(error1)) {			DEBUG(0, ("Unable to get key by index: %s\n",				win_errstr(error1)));			talloc_free(mem_ctx);			return error1;		}		if (oldkey != NULL) {			error2 = reg_key_get_value_by_name(mem_ctx, oldkey,							   name, &type2,							   &contents2);		} else			error2 = WERR_BADFILE;		if(!W_ERROR_IS_OK(error2) &&		   !W_ERROR_EQUAL(error2, WERR_BADFILE)) {			DEBUG(0, ("Error occured while getting value by name: %s\n",				win_errstr(error2)));			talloc_free(mem_ctx);			return error2;		}		if (W_ERROR_IS_OK(error2) &&		    data_blob_cmp(&contents1, &contents2) == 0)			continue;		callbacks->set_value(callback_data, path, name,				     type1, contents1);	}	/* Values that were deleted */	for (i = 0; i < old_num_values; i++) {		const char *name;		error1 = reg_key_get_value_by_index(mem_ctx, oldkey, i, &name,						    NULL, NULL);		if (!W_ERROR_IS_OK(error1)) {			DEBUG(0, ("Error ocurred getting value by index: %s\n",				win_errstr(error1)));			talloc_free(mem_ctx);			return error1;		}		error2 = reg_key_get_value_by_name(mem_ctx, newkey, name, NULL,						   NULL);		if (W_ERROR_IS_OK(error2))			continue;		if (!W_ERROR_EQUAL(error2, WERR_BADFILE)) {			DEBUG(0, ("Error occured while getting value by name: %s\n",				win_errstr(error2)));			return error2;		}		callbacks->del_value(callback_data, path, name);	}	talloc_free(mem_ctx);	return WERR_OK;}/** * Generate diff between two registry contexts */_PUBLIC_ WERROR reg_generate_diff(struct registry_context *ctx1,				  struct registry_context *ctx2,				  const struct reg_diff_callbacks *callbacks,				  void *callback_data){	int i;	WERROR error;	for(i = HKEY_FIRST; i <= HKEY_LAST; i++) {		struct registry_key *r1 = NULL, *r2 = NULL;		error = reg_get_predefined_key(ctx1, i, &r1);		if (!W_ERROR_IS_OK(error) &&		    !W_ERROR_EQUAL(error, WERR_BADFILE)) {			DEBUG(0, ("Unable to open hive %s for backend 1\n",				reg_get_predef_name(i)));		}		error = reg_get_predefined_key(ctx2, i, &r2);		if (!W_ERROR_IS_OK(error) &&		    !W_ERROR_EQUAL(error, WERR_BADFILE)) {			DEBUG(0, ("Unable to open hive %s for backend 2\n",				reg_get_predef_name(i)));		}		if (r1 == NULL && r2 == NULL)			continue;		error = reg_generate_diff_key(r1, r2, reg_get_predef_name(i),					      callbacks, callback_data);		if (!W_ERROR_IS_OK(error)) {			DEBUG(0, ("Unable to determine diff: %s\n",				win_errstr(error)));			return error;		}	}	if (callbacks->done != NULL) {		callbacks->done(callback_data);	}	return WERR_OK;}/** * Load diff file */_PUBLIC_ WERROR reg_diff_load(const char *filename,			      struct smb_iconv_convenience *iconv_convenience,			      const struct reg_diff_callbacks *callbacks,			      void *callback_data){	int fd;	char hdr[4];	fd = open(filename, O_RDONLY, 0);	if (fd == -1) {		DEBUG(0, ("Error opening registry patch file `%s'\n",			filename));		return WERR_GENERAL_FAILURE;	}	if (read(fd, &hdr, 4) != 4) {		DEBUG(0, ("Error reading registry patch file `%s'\n",			filename));		return WERR_GENERAL_FAILURE;	}	/* Reset position in file */	lseek(fd, 0, SEEK_SET);#if 0 /* These backends are not supported yet. */	if (strncmp(hdr, "CREG", 4) == 0) {		/* Must be a W9x CREG Config.pol file */		return reg_creg_diff_load(diff, fd);	} else if (strncmp(hdr, "regf", 4) == 0) {		/* Must be a REGF NTConfig.pol file */		return reg_regf_diff_load(diff, fd);	} else#endif	if (strncmp(hdr, "PReg", 4) == 0) {		/* Must be a GPO Registry.pol file */		return reg_preg_diff_load(fd, iconv_convenience, callbacks, callback_data);	} else {		/* Must be a normal .REG file */		return reg_dotreg_diff_load(fd, iconv_convenience, callbacks, callback_data);	}}/** * The reg_diff_apply functions */static WERROR reg_diff_apply_add_key(void *_ctx, const char *key_name){	struct registry_context *ctx = (struct registry_context *)_ctx;	struct registry_key *tmp;	char *buf, *buf_ptr;	WERROR error;	/* Recursively create the path */	buf = talloc_strdup(ctx, key_name);	buf_ptr = buf;	while (*buf_ptr++ != '\0' ) {		if (*buf_ptr == '\\') {			*buf_ptr = '\0';			error = reg_key_add_abs(ctx, ctx, buf, 0, NULL, &tmp);			if (!W_ERROR_EQUAL(error, WERR_ALREADY_EXISTS) &&				    !W_ERROR_IS_OK(error)) {				DEBUG(0, ("Error adding new key '%s': %s\n",					key_name, win_errstr(error)));				return error;			}			*buf_ptr++ = '\\';		}	}	/* Add the key */	error = reg_key_add_abs(ctx, ctx, key_name, 0, NULL, &tmp);	if (!W_ERROR_EQUAL(error, WERR_ALREADY_EXISTS) &&		    !W_ERROR_IS_OK(error)) {		DEBUG(0, ("Error adding new key '%s': %s\n",			key_name, win_errstr(error)));		return error;	}	return WERR_OK;}static WERROR reg_diff_apply_del_key(void *_ctx, const char *key_name){	struct registry_context *ctx = (struct registry_context *)_ctx;	WERROR error;	error = reg_key_del_abs(ctx, key_name);	if(!W_ERROR_IS_OK(error)) {		DEBUG(0, ("Unable to delete key '%s'\n", key_name));		return error;	}	return WERR_OK;}static WERROR reg_diff_apply_set_value(void *_ctx, const char *path,				       const char *value_name,				       uint32_t value_type, DATA_BLOB value){	struct registry_context *ctx = (struct registry_context *)_ctx;	struct registry_key *tmp;	WERROR error;	/* Open key */	error = reg_open_key_abs(ctx, ctx, path, &tmp);	if (W_ERROR_EQUAL(error, WERR_BADFILE)) {		DEBUG(0, ("Error opening key '%s'\n", path));		return error;	}	/* Set value */	error = reg_val_set(tmp, value_name,				 value_type, value);	if (!W_ERROR_IS_OK(error)) {		DEBUG(0, ("Error setting value '%s'\n", value_name));		return error;	}	return WERR_OK;}static WERROR reg_diff_apply_del_value(void *_ctx, const char *key_name,				       const char *value_name){	struct registry_context *ctx = (struct registry_context *)_ctx;	struct registry_key *tmp;	WERROR error;	/* Open key */	error = reg_open_key_abs(ctx, ctx, key_name, &tmp);	if (!W_ERROR_IS_OK(error)) {		DEBUG(0, ("Error opening key '%s'\n", key_name));		return error;	}	error = reg_del_value(tmp, value_name);	if (!W_ERROR_IS_OK(error)) {		DEBUG(0, ("Error deleting value '%s'\n", value_name));		return error;	}	return WERR_OK;}static WERROR reg_diff_apply_del_all_values(void *_ctx, const char *key_name){	struct registry_context *ctx = (struct registry_context *)_ctx;	struct registry_key *key;	WERROR error;	int i;	uint32_t num_values;	error = reg_open_key_abs(ctx, ctx, key_name, &key);	if (!W_ERROR_IS_OK(error)) {		DEBUG(0, ("Error opening key '%s'\n", key_name));		return error;	}	W_ERROR_NOT_OK_RETURN(reg_key_get_info(ctx, key, NULL,			       NULL, &num_values, NULL, NULL, NULL, NULL));	for (i = 0; i < num_values; i++) {		const char *name;		W_ERROR_NOT_OK_RETURN(reg_key_get_value_by_index(ctx, key, i,								 &name,								 NULL, NULL));		W_ERROR_NOT_OK_RETURN(reg_del_value(key, name));	}	return WERR_OK;}/** * Apply diff to a registry context */_PUBLIC_ WERROR reg_diff_apply(struct registry_context *ctx, const char *filename){	struct reg_diff_callbacks callbacks;	callbacks.add_key = reg_diff_apply_add_key;	callbacks.del_key = reg_diff_apply_del_key;	callbacks.set_value = reg_diff_apply_set_value;	callbacks.del_value = reg_diff_apply_del_value;	callbacks.del_all_values = reg_diff_apply_del_all_values;	callbacks.done = NULL;	return reg_diff_load(filename, lp_iconv_convenience(global_loadparm), 			     &callbacks, ctx);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -