예제 #1
0
/* Opens the registry file
 * Returns 1 if successful or -1 on error
 */
int registry_file_open(
     registry_file_t *registry_file,
     const libcstring_system_character_t *filename,
     libcerror_error_t **error )
{
	libcstring_system_character_t *name = NULL;
	libregf_key_t *sub_key              = NULL;
	libregf_value_t *value              = NULL;
	static char *function               = "registry_file_open";
	const char *sub_key_path            = NULL;
	const char *value_name              = NULL;
	size_t name_size                    = 0;
	size_t sub_key_path_length          = 0;
	size_t value_name_length            = 0;
	int number_of_sub_keys              = 0;
	int result                          = 0;

	if( registry_file == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid registry file.",
		 function );

		return( -1 );
	}
	if( registry_file->is_open != 0 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
		 "%s: invalid registry file already open.",
		 function );

		return( -1 );
	}
#if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER )
	if( libregf_file_open_wide(
	     registry_file->regf_file,
	     filename,
	     LIBREGF_OPEN_READ,
	     error ) != 1 )
#else
	if( libregf_file_open(
	     registry_file->regf_file,
	     filename,
	     LIBREGF_OPEN_READ,
	     error ) != 1 )
#endif
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_IO,
		 LIBCERROR_IO_ERROR_OPEN_FAILED,
		 "%s: unable to open REGF file.",
		 function );

		goto on_error;
	}
	if( libregf_file_get_root_key(
	     registry_file->regf_file,
	     &( registry_file->root_key ),
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to retrieve root key.",
		 function );

		goto on_error;
	}
	if( libregf_key_get_number_of_sub_keys(
	     registry_file->root_key,
	     &number_of_sub_keys,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to retrieve number of sub keys of root key.",
		 function );

		goto on_error;
	}
	result = 0;

	if( number_of_sub_keys == 1 )
	{
#if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER )
		result = libregf_key_get_utf16_name_size(
		          registry_file->root_key,
		          &name_size,
		          error );
#else
		result = libregf_key_get_utf8_name_size(
		          registry_file->root_key,
		          &name_size,
		          error );
#endif
		if( ( result != 1 )
		 || ( name_size == 0 ) )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve root key name size.",
			 function );

			goto on_error;
		}
		if( ( name_size > (size_t) SSIZE_MAX )
		 || ( ( sizeof( libcstring_system_character_t ) * name_size ) > (size_t) SSIZE_MAX ) )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
			 "%s: invalid name size value exceeds maximum.",
			 function );

			goto on_error;
		}
		name = libcstring_system_string_allocate(
			name_size );

		if( name == NULL )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_MEMORY,
			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
			 "%s: unable to create name string.",
			 function );

			goto on_error;
		}
#if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER )
		result = libregf_key_get_utf16_name(
			  registry_file->root_key,
			  (uint16_t *) name,
			  name_size,
			  error );
#else
		result = libregf_key_get_utf8_name(
			  registry_file->root_key,
			  (uint8_t *) name,
			  name_size,
			  error );
#endif
		if( result != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve root key name.",
			 function );

			goto on_error;
		}
		result = 0;

/* TODO what about Windows NT4 */
		if( name_size == 13 )
		{
			/* Root key used by Windows 2000, XP, 2003
			 */
			if( libcstring_system_string_compare_no_case(
			     name,
			     _LIBCSTRING_SYSTEM_STRING( "$$$PROTO.HIV" ),
			     12 ) == 0 )
			{
				result = 1;
			}
		}
		else if( name_size == 53 )
		{
			/* Root key used by Windows Vista, 2008, 7
			 */
			if( libcstring_system_string_compare_no_case(
			     name,
			     _LIBCSTRING_SYSTEM_STRING( "CMI-CreateHive{" ),
			     15 ) == 0 )
			{
				if( name[ 51 ] == (libcstring_system_character_t) '}' )
				{
					result = 1;
				}
			}
		}
		else if( name_size == 58 )
		{
			/* Root key used by Windows 8
			 */
			if( libcstring_system_string_compare_no_case(
			     name,
			     _LIBCSTRING_SYSTEM_STRING( "CsiTool-CreateHive-{" ),
			     20 ) == 0 )
			{
				if( name[ 56 ] == (libcstring_system_character_t) '}' )
				{
					result = 1;
				}
			}
		}
		memory_free(
		 name );

		name = NULL;
	}
	if( result != 0 )
	{
		if( libregf_key_get_sub_key(
		     registry_file->root_key,
		     0,
		     &( registry_file->base_key ),
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve base key.",
			 function );

			goto on_error;
		}
	}
	else
	{
		/* E.g. for the SAM registry file the root key is the base
		 */
		registry_file->base_key = registry_file->root_key;
	}
	/* Determine the registry file type based on the name of the base key
	 */
/* TODO refactor to separate function */
#if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER )
	result = libregf_key_get_utf16_name_size(
		  registry_file->base_key,
		  &name_size,
		  error );
#else
	result = libregf_key_get_utf8_name_size(
		  registry_file->base_key,
		  &name_size,
		  error );
#endif
	if( ( result != 1 )
	 || ( name_size == 0 ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to retrieve base key name size.",
		 function );

		goto on_error;
	}
	if( ( name_size > (size_t) SSIZE_MAX )
	 || ( ( sizeof( libcstring_system_character_t ) * name_size ) > (size_t) SSIZE_MAX ) )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
		 "%s: invalid name size value exceeds maximum.",
		 function );

		goto on_error;
	}
	name = libcstring_system_string_allocate(
		name_size );

	if( name == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_MEMORY,
		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
		 "%s: unable to create name string.",
		 function );

		goto on_error;
	}
#if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER )
	result = libregf_key_get_utf16_name(
		  registry_file->base_key,
		  (uint16_t *) name,
		  name_size,
		  error );
#else
	result = libregf_key_get_utf8_name(
		  registry_file->base_key,
		  (uint8_t *) name,
		  name_size,
		  error );
#endif
	if( result != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to retrieve base key name.",
		 function );

		goto on_error;
	}
/* TODO add more types */
	if( name_size == 4 )
	{
		if( libcstring_system_string_compare_no_case(
		     name,
		     _LIBCSTRING_SYSTEM_STRING( "SAM" ),
		     3 ) == 0 )
		{
			registry_file->type = REGISTRY_FILE_TYPE_SAM;
		}
	}
	memory_free(
	 name );

	name = NULL;
/* TODO still needed ? */
	if( libregf_key_get_number_of_sub_keys(
	     registry_file->base_key,
	     &number_of_sub_keys,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to retrieve number of sub keys of base key.",
		 function );

		goto on_error;
	}
/* TODO refactor to separate function */
	/* Get the current control set from:
	 * SYSTEM\Select\Current
	 */
	sub_key_path = "Select";

	sub_key_path_length = libcstring_narrow_string_length(
	                       sub_key_path );

	result = libregf_key_get_sub_key_by_utf8_path(
		  registry_file->base_key,
		  (uint8_t *) sub_key_path,
		  sub_key_path_length,
		  &sub_key,
		  error );

	if( result == -1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to retrieve sub key: %s.",
		 function,
		 sub_key_path );

		goto on_error;
	}
	else if( result != 0 )
	{
		value_name = "Current";

		value_name_length = libcstring_narrow_string_length(
		                     value_name );

		result = libregf_key_get_value_by_utf8_name(
			  sub_key,
			  (uint8_t *) value_name,
			  value_name_length,
			  &value,
			  error );

		if( result == -1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve value: %s.",
			 function,
			 value_name );

			goto on_error;
		}
		else if( result != 0 )
		{
			if( libregf_value_get_value_32bit(
			     value,
			     &( registry_file->current_control_set ),
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
				 "%s: unable to retrieve 32-bit value: %s.",
				 function,
				 value_name );

				goto on_error;
			}
			if( libregf_value_free(
			     &value,
			     error ) != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
				 "%s: unable to free value.",
				 function );

				goto on_error;
			}
		}
	}
	if( libregf_key_free(
	     &sub_key,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
		 "%s: unable to free sub key.",
		 function );

		goto on_error;
	}
	/* Retrieve the control set 1 key: SYSTEM\ControlSet001
	 */
	sub_key_path = "ControlSet001";

	sub_key_path_length = libcstring_narrow_string_length(
	                       sub_key_path );

	result = libregf_key_get_sub_key_by_utf8_path(
		  registry_file->base_key,
		  (uint8_t *) sub_key_path,
		  sub_key_path_length,
		  &( registry_file->control_set1_key ),
		  error );

	if( result == -1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to retrieve sub key: %s.",
		 function,
		 sub_key_path );

		goto on_error;
	}
	/* Retrieve the control set 2 key: SYSTEM\ControlSet002
	 */
	sub_key_path = "ControlSet002";

	sub_key_path_length = libcstring_narrow_string_length(
	                       sub_key_path );

	result = libregf_key_get_sub_key_by_utf8_path(
		  registry_file->base_key,
		  (uint8_t *) sub_key_path,
		  sub_key_path_length,
		  &( registry_file->control_set2_key ),
		  error );

	if( result == -1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to retrieve sub key: %s.",
		 function,
		 sub_key_path );

		goto on_error;
	}
	if( ( registry_file->current_control_set != 0 )
	 || ( registry_file->control_set1_key != NULL )
	 || ( registry_file->control_set2_key != NULL ) )
	{
		if( ( registry_file->current_control_set != 1 )
		 && ( registry_file->current_control_set != 2 ) )
		{
/* TODO print debug notification */
			registry_file->current_control_set = 1;
		}
		if( ( registry_file->current_control_set == 1 )
		 && ( registry_file->control_set1_key != NULL ) )
		{
			registry_file->current_control_set_key = registry_file->control_set1_key;
		}
		else if( ( registry_file->current_control_set == 2 )
		      && ( registry_file->control_set2_key != NULL ) )
		{
			registry_file->current_control_set_key = registry_file->control_set2_key;
		}
	}
	registry_file->is_open = 1;

	return( 1 );

on_error:
	if( value != NULL )
	{
		libregf_value_free(
		 &value,
		 NULL );
	}
	if( sub_key != NULL )
	{
		libregf_key_free(
		 &sub_key,
		 NULL );
	}
	if( registry_file->control_set2_key != NULL )
	{
		libregf_key_free(
		 &( registry_file->control_set2_key ),
		 NULL );
	}
	if( registry_file->control_set1_key != NULL )
	{
		libregf_key_free(
		 &( registry_file->control_set1_key ),
		 NULL );
	}
	if( ( registry_file->base_key != NULL )
	 && ( registry_file->base_key != registry_file->root_key ) )
	{
		libregf_key_free(
		 &( registry_file->base_key ),
		 NULL );
	}
	if( name != NULL )
	{
		memory_free(
		 name );
	}
	if( registry_file->root_key != NULL )
	{
		libregf_key_free(
		 &( registry_file->root_key ),
		 NULL );
	}
	libregf_file_close(
	 registry_file->regf_file,
	 NULL );

	return( -1 );
}
예제 #2
0
/* Exports a key
 * Returns the 1 if succesful or -1 on error
 */
int export_handle_export_key(
     export_handle_t *export_handle,
     libregf_key_t *key,
     log_handle_t *log_handle,
     libcerror_error_t **error )
{
	system_character_t *value_string = NULL;
	libregf_key_t *sub_key           = NULL;
	libregf_value_t *value           = NULL;
	uint8_t *data                    = NULL;
	static char *function            = "export_handle_export_key";
	size_t data_size                 = 0;
	size_t expected_data_size        = 0;
	size_t value_string_size         = 0;
	ssize_t print_count              = 0;
	uint64_t value_64bit             = 0;
	uint32_t value_32bit             = 0;
	uint32_t value_type              = 0;
	int number_of_sub_keys           = 0;
	int number_of_values             = 0;
	int result                       = 0;
	int sub_key_index                = 0;
	int value_index                  = 0;

	if( export_handle == NULL )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
		 "%s: invalid export handle.",
		 function );

		return( -1 );
	}
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
	result = libregf_key_get_utf16_name_size(
	          key,
	          &value_string_size,
	          error );
#else
	result = libregf_key_get_utf8_name_size(
	          key,
	          &value_string_size,
	          error );
#endif
	if( result != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to retrieve key name size.",
		 function );

		goto on_error;
	}
	if( value_string_size > 0 )
	{
		if( ( value_string_size > (size_t) SSIZE_MAX )
		 || ( ( sizeof( system_character_t ) * value_string_size ) > (size_t) SSIZE_MAX ) )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
			 "%s: invalid name size value exceeds maximum.",
			 function );

			goto on_error;
		}
		value_string = system_string_allocate(
		                value_string_size );

		if( value_string == NULL )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_MEMORY,
			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
			 "%s: unable to create name string.",
			 function );

			goto on_error;
		}
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
		result = libregf_key_get_utf16_name(
		          key,
		          (uint16_t *) value_string,
		          value_string_size,
		          error );
#else
		result = libregf_key_get_utf8_name(
		          key,
		          (uint8_t *) value_string,
		          value_string_size,
		          error );
#endif
		if( result != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve key name.",
			 function );

			goto on_error;
		}
/* TODO print full key path */
		fprintf(
		 export_handle->notify_stream,
		 "Key: %" PRIs_SYSTEM "\n",
		 value_string );

		memory_free(
		 value_string );

		value_string = NULL;
	}
#ifdef TODO
/* TODO fix this */
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
	result = libregf_key_get_utf16_class_name_size(
	          key,
	          &value_string_size,
	          error );
#else
	result = libregf_key_get_utf8_class_name_size(
	          key,
	          &value_string_size,
	          error );
#endif
	if( result == -1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to retrieve the class name size.",
		 function );

		goto on_error;
	}
	if( ( result != 0 )
	 && ( value_string_size > 0 ) )
	{
		if( ( value_string_size > (size_t) SSIZE_MAX )
		 || ( ( sizeof( system_character_t ) * value_string_size ) > (size_t) SSIZE_MAX ) )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
			 "%s: invalid name size value exceeds maximum.",
			 function );

			goto on_error;
		}
		value_string = system_string_allocate(
		                value_string_size );

		if( value_string == NULL )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_MEMORY,
			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
			 "%s: unable to create name string.",
			 function );

			goto on_error;
		}
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
		result = libregf_key_get_utf16_class_name(
		          key,
		          (uint16_t *) value_string,
		          value_string_size,
		          error );
#else
		result = libregf_key_get_utf8_class_name(
		          key,
		          (uint8_t *) value_string,
		          value_string_size,
		          error );
#endif
		if( result != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve class name.",
			 function );

			goto on_error;
		}
		fprintf(
		 export_handle->notify_stream,
		 "Class name: %" PRIs_SYSTEM "\n",
		 value_string );

		memory_free(
		 value_string );

		value_string = NULL;
	}
#endif
	if( libregf_key_get_number_of_values(
	     key,
	     &number_of_values,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to retrieve number of values.",
		 function );

		goto on_error;
	}
	for( value_index = 0;
	     value_index < number_of_values;
	     value_index++ )
	{
		if( libregf_key_get_value(
		     key,
		     value_index,
		     &value,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve value: %d.",
			 function,
			 value_index );

			goto on_error;
		}
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
		result = libregf_value_get_utf16_name_size(
		          value,
		          &value_string_size,
		          error );
#else
		result = libregf_value_get_utf8_name_size(
		          value,
		          &value_string_size,
		          error );
#endif
		if( result != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve value name size.",
			 function );

			goto on_error;
		}
		if( value_string_size > 0 )
		{
			if( ( value_string_size > (size_t) SSIZE_MAX )
			 || ( ( sizeof( system_character_t ) * value_string_size ) > (size_t) SSIZE_MAX ) )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
				 "%s: invalid name size value exceeds maximum.",
				 function );

				goto on_error;
			}
			value_string = system_string_allocate(
			                value_string_size );

			if( value_string == NULL )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_MEMORY,
				 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
				 "%s: unable to create name string.",
				 function );

				goto on_error;
			}
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
			result = libregf_value_get_utf16_name(
			          value,
			          (uint16_t *) value_string,
			          value_string_size,
			          error );
#else
			result = libregf_value_get_utf8_name(
			          value,
			          (uint8_t *) value_string,
			          value_string_size,
			          error );
#endif
			if( result != 1 )
			{
				libcerror_error_set(
				 error,
				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
				 "%s: unable to retrieve value name.",
				 function );

				goto on_error;
			}
			fprintf(
			 export_handle->notify_stream,
			 "Value: %d %" PRIs_SYSTEM "\n",
			 value_index,
			 value_string );

			memory_free(
			 value_string );

			value_string = NULL;
		}
		else
		{
			fprintf(
			 export_handle->notify_stream,
			 "Value: %d (default)\n",
			 value_index );
		}
		if( libregf_value_get_value_type(
		     value,
		     &value_type,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve value type.",
			 function );

			goto on_error;
		}
		switch( value_type )
		{
			case LIBREGF_VALUE_TYPE_UNDEFINED:
				fprintf(
				 export_handle->notify_stream,
				 "Type: undefined (none)\n" );
				break;

			case LIBREGF_VALUE_TYPE_STRING:
				fprintf(
				 export_handle->notify_stream,
				 "Type: string\n" );
				break;

			case LIBREGF_VALUE_TYPE_EXPANDABLE_STRING:
				fprintf(
				 export_handle->notify_stream,
				 "Type: expandable string\n" );
				break;

			case LIBREGF_VALUE_TYPE_BINARY_DATA:
				fprintf(
				 export_handle->notify_stream,
				 "Type: binary data\n" );
				break;

			case LIBREGF_VALUE_TYPE_INTEGER_32BIT_LITTLE_ENDIAN:
				fprintf(
				 export_handle->notify_stream,
				 "Type: 32-bit integer little-endian\n" );
				break;

			case LIBREGF_VALUE_TYPE_INTEGER_32BIT_BIG_ENDIAN:
				fprintf(
				 export_handle->notify_stream,
				 "Type: 32-bit integer big-endian\n" );
				break;

			case LIBREGF_VALUE_TYPE_SYMBOLIC_LINK:
				fprintf(
				 export_handle->notify_stream,
				 "Type: symbolic link\n" );
				break;

			case LIBREGF_VALUE_TYPE_MULTI_VALUE_STRING:
				fprintf(
				 export_handle->notify_stream,
				 "Type: multi-value string\n" );
				break;

			case LIBREGF_VALUE_TYPE_RESOURCE_LIST:
				fprintf(
				 export_handle->notify_stream,
				 "Type: resource list\n" );
				break;

			case LIBREGF_VALUE_TYPE_FULL_RESOURCE_DESCRIPTOR:
				fprintf(
				 export_handle->notify_stream,
				 "Type: full resource descriptor\n" );
				break;

			case LIBREGF_VALUE_TYPE_RESOURCE_REQUIREMENTS_LIST:
				fprintf(
				 export_handle->notify_stream,
				 "Type: resource requirements list\n" );
				break;

			case LIBREGF_VALUE_TYPE_INTEGER_64BIT_LITTLE_ENDIAN:
				fprintf(
				 export_handle->notify_stream,
				 "Type: 64-bit integer little-endian\n" );
				break;

			default:
				fprintf(
				 export_handle->notify_stream,
				 "Type: unknown: 0x%08" PRIx32 "\n",
				 value_type );
				break;
		}
		if( libregf_value_get_value_data_size(
		     value,
		     &data_size,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve value data size.",
			 function );

			goto on_error;
		}
		fprintf(
		 export_handle->notify_stream,
		 "Data size: %" PRIzd "\n",
		 data_size );

		switch( value_type )
		{
			case LIBREGF_VALUE_TYPE_STRING:
			case LIBREGF_VALUE_TYPE_EXPANDABLE_STRING:
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
				result = libregf_value_get_value_utf16_string_size(
					  value,
					  &value_string_size,
					  error );
#else
				result = libregf_value_get_value_utf8_string_size(
					  value,
					  &value_string_size,
					  error );
#endif
				if( result != 1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
					 "%s: unable to retrieve value string size.",
					 function );

					goto on_error;
				}
				if( value_string_size > 0 )
				{
					if( ( value_string_size > (size_t) SSIZE_MAX )
					 || ( ( sizeof( system_character_t ) * value_string_size ) > (size_t) SSIZE_MAX ) )
					{
						libcerror_error_set(
						 error,
						 LIBCERROR_ERROR_DOMAIN_RUNTIME,
						 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
						 "%s: invalid value string size value exceeds maximum.",
						 function );

						goto on_error;
					}
					value_string = system_string_allocate(
							value_string_size );

					if( value_string == NULL )
					{
						libcerror_error_set(
						 error,
						 LIBCERROR_ERROR_DOMAIN_MEMORY,
						 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
						 "%s: unable to create value string.",
						 function );

						goto on_error;
					}
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
					result = libregf_value_get_value_utf16_string(
						  value,
						  (uint16_t *) value_string,
						  value_string_size,
						  error );
#else
					result = libregf_value_get_value_utf8_string(
						  value,
						  (uint8_t *) value_string,
						  value_string_size,
						  error );
#endif
					if( result != 1 )
					{
						libcerror_error_set(
						 error,
						 LIBCERROR_ERROR_DOMAIN_RUNTIME,
						 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
						 "%s: unable to retrieve value string.",
						 function );

						goto on_error;
					}
					fprintf(
					 export_handle->notify_stream,
					 "Data: %" PRIs_SYSTEM "\n",
					 value_string );

					memory_free(
					 value_string );

					value_string = NULL;
				}
				else
				{
					fprintf(
					 export_handle->notify_stream,
					 "Data:\n" );
				}
				result = libregf_value_get_value_utf16_string_size(
					  value,
					  &expected_data_size,
					  error );

				if( result != 1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
					 "%s: unable to retrieve value UTF-16 string size.",
					 function );

					goto on_error;
				}
				expected_data_size *= 2;

				if( expected_data_size == ( data_size + 2 ) )
				{
					expected_data_size -= 2;
				}
				break;

			case LIBREGF_VALUE_TYPE_INTEGER_32BIT_LITTLE_ENDIAN:
			case LIBREGF_VALUE_TYPE_INTEGER_32BIT_BIG_ENDIAN:
				if( data_size == 4 )
				{
					if( libregf_value_get_value_32bit(
					     value,
					     &value_32bit,
					     error ) != 1 )
					{
						libcerror_error_set(
						 error,
						 LIBCERROR_ERROR_DOMAIN_RUNTIME,
						 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
						 "%s: unable to retrieve 32-bit value.",
						 function );

						goto on_error;
					}
					fprintf(
					 export_handle->notify_stream,
					 "Data: %" PRIu32 "\n",
					 value_32bit );
				}
				expected_data_size = 4;

				break;

			case LIBREGF_VALUE_TYPE_INTEGER_64BIT_LITTLE_ENDIAN:
				if( data_size == 8 )
				{
					if( libregf_value_get_value_64bit(
					     value,
					     &value_64bit,
					     error ) != 1 )
					{
						libcerror_error_set(
						 error,
						 LIBCERROR_ERROR_DOMAIN_RUNTIME,
						 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
						 "%s: unable to retrieve 64-bit value.",
						 function );

						goto on_error;
					}
					fprintf(
					 export_handle->notify_stream,
					 "Data: %" PRIu64 "\n",
					 value_64bit );
				}
				expected_data_size = 8;

				break;

			default:
				expected_data_size = 0;

				break;
		}
		if( data_size != expected_data_size )
		{
			if( expected_data_size != 0 )
			{
				fprintf(
				 export_handle->notify_stream,
				 "Mismatch in data size and that required for data type.\n" );
			}
			if( data_size > 0 )
			{
				data = (uint8_t *) memory_allocate(
						    sizeof( uint8_t ) * data_size );

				if( data == NULL )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_MEMORY,
					 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
					 "%s: unable to create value data.",
					 function );

					goto on_error;
				}
				if( libregf_value_get_value_data(
				     value,
				     data,
				     data_size,
				     error ) != 1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
					 "%s: unable to retrieve value data.",
					 function );

					goto on_error;
				}
				fprintf(
				 export_handle->notify_stream,
				 "Data:\n" );

				print_count = export_handle_print_data(
					       export_handle,
					       export_handle->notify_stream,
					       data,
					       data_size,
					       error );

				if( print_count == -1 )
				{
					libcerror_error_set(
					 error,
					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
					 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
					 "%s: unable to print value data.",
					 function );

					goto on_error;
				}
				memory_free(
				 data );

				data = NULL;
			}
			else
			{
				fprintf(
				 export_handle->notify_stream,
				 "\n" );
			}
		}
		else
		{
			fprintf(
			 export_handle->notify_stream,
			 "\n" );
		}
		if( libregf_value_free(
		     &value,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
			 "%s: unable to free value: %d.",
			 function,
			 value_index );

			goto on_error;
		}
	}
	if( number_of_values == 0 )
	{
		fprintf(
		 export_handle->notify_stream,
		 "\n" );
	}
	if( libregf_key_get_number_of_sub_keys(
	     key,
	     &number_of_sub_keys,
	     error ) != 1 )
	{
		libcerror_error_set(
		 error,
		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
		 "%s: unable to retrieve number of sub keys.",
		 function );

		goto on_error;
	}
	for( sub_key_index = 0;
	     sub_key_index < number_of_sub_keys;
	     sub_key_index++ )
	{
		if( export_handle->abort != 0 )
		{
			goto on_error;
		}
		if( libregf_key_get_sub_key(
		     key,
		     sub_key_index,
		     &sub_key,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
			 "%s: unable to retrieve sub key: %d.",
			 function,
			 sub_key_index );

			goto on_error;
		}
		if( export_handle_export_key(
		     export_handle,
		     sub_key,
		     log_handle,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_GENERIC,
			 "%s: unable to export sub key: %d.",
			 function,
			 sub_key_index );

			goto on_error;
		}
		if( libregf_key_free(
		     &sub_key,
		     error ) != 1 )
		{
			libcerror_error_set(
			 error,
			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
			 "%s: unable to free sub key: %d.",
			 function,
			 sub_key_index );

			goto on_error;
		}
	}
	return( 1 );

on_error:
	if( sub_key != NULL )
	{
		libregf_key_free(
		 &sub_key,
		 NULL );
	}
	if( data != NULL )
	{
		memory_free(
		 data );
	}
	if( value != NULL )
	{
		libregf_value_free(
		 &value,
		 NULL );
	}
	if( value_string != NULL )
	{
		memory_free(
		 value_string );
	}
	return( -1 );
}