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

📄 regfio.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Unix SMB/CIFS implementation. * Windows NT registry I/O library * Copyright (c) Gerald (Jerry) Carter               2005 * * 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 2 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, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */#include "includes.h"#include "regfio.h"/******************************************************************* * * TODO : Right now this code basically ignores classnames. * ******************************************************************//**************************************************************************************************************************************/static int write_block( REGF_FILE *file, prs_struct *ps, uint32 offset ){	int bytes_written, returned;	char *buffer = prs_data_p( ps );	uint32 buffer_size = prs_data_size( ps );	SMB_STRUCT_STAT sbuf;	if ( file->fd == -1 )		return -1;	/* check for end of file */	if ( sys_fstat( file->fd, &sbuf ) ) {		DEBUG(0,("write_block: stat() failed! (%s)\n", strerror(errno)));		return -1;	}	if ( lseek( file->fd, offset, SEEK_SET ) == -1 ) {		DEBUG(0,("write_block: lseek() failed! (%s)\n", strerror(errno) ));		return -1;	}		bytes_written = returned = 0;	while ( bytes_written < buffer_size ) {		if ( (returned = write( file->fd, buffer+bytes_written, buffer_size-bytes_written )) == -1 ) {			DEBUG(0,("write_block: write() failed! (%s)\n", strerror(errno) ));			return False;		}						bytes_written += returned;	}		return bytes_written;}/**************************************************************************************************************************************/static int read_block( REGF_FILE *file, prs_struct *ps, uint32 file_offset, uint32 block_size ){	int bytes_read, returned;	char *buffer;	SMB_STRUCT_STAT sbuf;	/* check for end of file */	if ( sys_fstat( file->fd, &sbuf ) ) {		DEBUG(0,("read_block: stat() failed! (%s)\n", strerror(errno)));		return -1;	}	if ( (size_t)file_offset >= sbuf.st_size )		return -1;		/* if block_size == 0, we are parsing HBIN records and need 	   to read some of the header to get the block_size from there */	   	if ( block_size == 0 ) {		char hdr[0x20];		if ( lseek( file->fd, file_offset, SEEK_SET ) == -1 ) {			DEBUG(0,("read_block: lseek() failed! (%s)\n", strerror(errno) ));			return -1;		}		returned = read( file->fd, hdr, 0x20 );		if ( (returned == -1) || (returned < 0x20) ) {			DEBUG(0,("read_block: failed to read in HBIN header. Is the file corrupt?\n"));			return -1;		}		/* make sure this is an hbin header */		if ( strncmp( hdr, "hbin", HBIN_HDR_SIZE ) != 0 ) {			DEBUG(0,("read_block: invalid block header!\n"));			return -1;		}		block_size = IVAL( hdr, 0x08 );	}	DEBUG(10,("read_block: block_size == 0x%x\n", block_size ));	/* set the offset, initialize the buffer, and read the block from disk */	if ( lseek( file->fd, file_offset, SEEK_SET ) == -1 ) {		DEBUG(0,("read_block: lseek() failed! (%s)\n", strerror(errno) ));		return -1;	}		prs_init( ps, block_size, file->mem_ctx, UNMARSHALL );	buffer = prs_data_p( ps );	bytes_read = returned = 0;	while ( bytes_read < block_size ) {		if ( (returned = read( file->fd, buffer+bytes_read, block_size-bytes_read )) == -1 ) {			DEBUG(0,("read_block: read() failed (%s)\n", strerror(errno) ));			return False;		}		if ( (returned == 0) && (bytes_read < block_size) ) {			DEBUG(0,("read_block: not a vald registry file ?\n" ));			return False;		}					bytes_read += returned;	}		return bytes_read;}/**************************************************************************************************************************************/static BOOL write_hbin_block( REGF_FILE *file, REGF_HBIN *hbin ){	if ( !hbin->dirty )		return True;	/* write free space record if any is available */	if ( hbin->free_off != REGF_OFFSET_NONE ) {		uint32 header = 0xffffffff;		if ( !prs_set_offset( &hbin->ps, hbin->free_off-sizeof(uint32) ) )			return False;		if ( !prs_uint32( "free_size", &hbin->ps, 0, &hbin->free_size ) )			return False;		if ( !prs_uint32( "free_header", &hbin->ps, 0, &header ) )			return False;	}	hbin->dirty = (write_block( file, &hbin->ps, hbin->file_off ) != -1);	return hbin->dirty;}/**************************************************************************************************************************************/static BOOL hbin_block_close( REGF_FILE *file, REGF_HBIN *hbin ){	REGF_HBIN *p;	/* remove the block from the open list and flush it to disk */	for ( p=file->block_list; p && p!=hbin; p=p->next )		;;	if ( p == hbin ) {		DLIST_REMOVE( file->block_list, hbin );	}	else		DEBUG(0,("hbin_block_close: block not in open list!\n"));	if ( !write_hbin_block( file, hbin ) )		return False;	return True;}/**************************************************************************************************************************************/static BOOL prs_regf_block( const char *desc, prs_struct *ps, int depth, REGF_FILE *file ){	prs_debug(ps, depth, desc, "prs_regf_block");	depth++;		if ( !prs_uint8s( True, "header", ps, depth, (uint8*)file->header, sizeof( file->header )) )		return False;		/* yes, these values are always identical so store them only once */		if ( !prs_uint32( "unknown1", ps, depth, &file->unknown1 ))		return False;	if ( !prs_uint32( "unknown1 (again)", ps, depth, &file->unknown1 ))		return False;	/* get the modtime */		if ( !prs_set_offset( ps, 0x0c ) )		return False;	if ( !smb_io_time( "modtime", &file->mtime, ps, depth ) )		return False;	/* constants */		if ( !prs_uint32( "unknown2", ps, depth, &file->unknown2 ))		return False;	if ( !prs_uint32( "unknown3", ps, depth, &file->unknown3 ))		return False;	if ( !prs_uint32( "unknown4", ps, depth, &file->unknown4 ))		return False;	if ( !prs_uint32( "unknown5", ps, depth, &file->unknown5 ))		return False;	/* get file offsets */		if ( !prs_set_offset( ps, 0x24 ) )		return False;	if ( !prs_uint32( "data_offset", ps, depth, &file->data_offset ))		return False;	if ( !prs_uint32( "last_block", ps, depth, &file->last_block ))		return False;			/* one more constant */		if ( !prs_uint32( "unknown6", ps, depth, &file->unknown6 ))		return False;			/* get the checksum */		if ( !prs_set_offset( ps, 0x01fc ) )		return False;	if ( !prs_uint32( "checksum", ps, depth, &file->checksum ))		return False;		return True;}/**************************************************************************************************************************************/static BOOL prs_hbin_block( const char *desc, prs_struct *ps, int depth, REGF_HBIN *hbin ){	uint32 block_size2;	prs_debug(ps, depth, desc, "prs_regf_block");	depth++;		if ( !prs_uint8s( True, "header", ps, depth, (uint8*)hbin->header, sizeof( hbin->header )) )		return False;	if ( !prs_uint32( "first_hbin_off", ps, depth, &hbin->first_hbin_off ))		return False;	/* The dosreg.cpp comments say that the block size is at 0x1c.	   According to a WINXP NTUSER.dat file, this is wrong.  The block_size	   is at 0x08 */	if ( !prs_uint32( "block_size", ps, depth, &hbin->block_size ))		return False;	block_size2 = hbin->block_size;	prs_set_offset( ps, 0x1c );	if ( !prs_uint32( "block_size2", ps, depth, &block_size2 ))		return False;	if ( MARSHALLING(ps) )		hbin->dirty = True;		return True;}/**************************************************************************************************************************************/static BOOL prs_nk_rec( const char *desc, prs_struct *ps, int depth, REGF_NK_REC *nk ){	uint16 class_length, name_length;	uint32 start;	uint32 data_size, start_off, end_off;	uint32 unknown_off = REGF_OFFSET_NONE;	nk->hbin_off = prs_offset( ps );	start = nk->hbin_off;		prs_debug(ps, depth, desc, "prs_nk_rec");	depth++;		/* back up and get the data_size */		if ( !prs_set_offset( ps, prs_offset(ps)-sizeof(uint32)) )		return False;	start_off = prs_offset( ps );	if ( !prs_uint32( "rec_size", ps, depth, &nk->rec_size ))		return False;		if ( !prs_uint8s( True, "header", ps, depth, (uint8*)nk->header, sizeof( nk->header )) )		return False;			if ( !prs_uint16( "key_type", ps, depth, &nk->key_type ))		return False;	if ( !smb_io_time( "mtime", &nk->mtime, ps, depth ))		return False;			if ( !prs_set_offset( ps, start+0x0010 ) )		return False;	if ( !prs_uint32( "parent_off", ps, depth, &nk->parent_off ))		return False;	if ( !prs_uint32( "num_subkeys", ps, depth, &nk->num_subkeys ))		return False;			if ( !prs_set_offset( ps, start+0x001c ) )		return False;	if ( !prs_uint32( "subkeys_off", ps, depth, &nk->subkeys_off ))		return False;	if ( !prs_uint32( "unknown_off", ps, depth, &unknown_off) )		return False;			if ( !prs_set_offset( ps, start+0x0024 ) )		return False;	if ( !prs_uint32( "num_values", ps, depth, &nk->num_values ))		return False;	if ( !prs_uint32( "values_off", ps, depth, &nk->values_off ))		return False;	if ( !prs_uint32( "sk_off", ps, depth, &nk->sk_off ))		return False;	if ( !prs_uint32( "classname_off", ps, depth, &nk->classname_off ))		return False;	if ( !prs_uint32( "max_bytes_subkeyname", ps, depth, &nk->max_bytes_subkeyname))		return False;	if ( !prs_uint32( "max_bytes_subkeyclassname", ps, depth, &nk->max_bytes_subkeyclassname))		return False;	if ( !prs_uint32( "max_bytes_valuename", ps, depth, &nk->max_bytes_valuename))		return False;	if ( !prs_uint32( "max_bytes_value", ps, depth, &nk->max_bytes_value))		return False;	if ( !prs_uint32( "unknown index", ps, depth, &nk->unk_index))		return False;	name_length = nk->keyname ? strlen(nk->keyname) : 0 ;	class_length = nk->classname ? strlen(nk->classname) : 0 ;	if ( !prs_uint16( "name_length", ps, depth, &name_length ))		return False;	if ( !prs_uint16( "class_length", ps, depth, &class_length ))		return False;				if ( class_length ) {		;;	}		if ( name_length ) {		if ( UNMARSHALLING(ps) ) {			if ( !(nk->keyname = PRS_ALLOC_MEM( ps, char, name_length+1 )) )				return False;		}		if ( !prs_uint8s( True, "name", ps, depth, (uint8*)nk->keyname, name_length) )			return False;		if ( UNMARSHALLING(ps) ) 			nk->keyname[name_length] = '\0';	}	end_off = prs_offset( ps );	/* data_size must be divisible by 8 and large enough to hold the original record */	data_size = ((start_off - end_off) & 0xfffffff8 );	if ( data_size > nk->rec_size )		DEBUG(10,("Encountered reused record (0x%x < 0x%x)\n", data_size, nk->rec_size));	if ( MARSHALLING(ps) )		nk->hbin->dirty = True;	return True;}/**************************************************************************************************************************************/static uint32 regf_block_checksum( prs_struct *ps ){	char *buffer = prs_data_p( ps );	uint32 checksum, x;	int i;	/* XOR of all bytes 0x0000 - 0x01FB */			checksum = x = 0;		for ( i=0; i<0x01FB; i+=4 ) {		x = IVAL(buffer, i );		checksum ^= x;	}		return checksum;}/**************************************************************************************************************************************/static BOOL read_regf_block( REGF_FILE *file ){	prs_struct ps;	uint32 checksum;		/* grab the first block from the file */			if ( read_block( file, &ps, 0, REGF_BLOCKSIZE ) == -1 )		return False;		/* parse the block and verify the checksum */		if ( !prs_regf_block( "regf_header", &ps, 0, file ) )		return False;				checksum = regf_block_checksum( &ps );		prs_mem_free( &ps );		if ( file->checksum !=  checksum ) {		DEBUG(0,("read_regf_block: invalid checksum\n" ));		return False;	}	return True;}/**************************************************************************************************************************************/static REGF_HBIN* read_hbin_block( REGF_FILE *file, off_t offset ){	REGF_HBIN *hbin;	uint32 record_size, curr_off, block_size, header;		if ( !(hbin = TALLOC_ZERO_P(file->mem_ctx, REGF_HBIN)) ) 		return NULL;	hbin->file_off = offset;	hbin->free_off = -1;			if ( read_block( file, &hbin->ps, offset, 0 ) == -1 )		return NULL;		if ( !prs_hbin_block( "hbin", &hbin->ps, 0, hbin ) )		return NULL;		/* this should be the same thing as hbin->block_size but just in case */	block_size = prs_data_size( &hbin->ps );		/* Find the available free space offset.  Always at the end,	   so walk the record list and stop when you get to the end.	   The end is defined by a record header of 0xffffffff.  The 

⌨️ 快捷键说明

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