/* * Data definition functions * * Copyright (C) 2009-2023, Joachim Metz * * Refer to AUTHORS for acknowledgements. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser 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 Lesser General Public License * along with this program. If not, see . */ #include #include #include #include #include "libesedb_catalog_definition.h" #include "libesedb_column_type.h" #include "libesedb_data_definition.h" #include "libesedb_debug.h" #include "libesedb_definitions.h" #include "libesedb_io_handle.h" #include "libesedb_libbfio.h" #include "libesedb_libcdata.h" #include "libesedb_libcerror.h" #include "libesedb_libcnotify.h" #include "libesedb_libfcache.h" #include "libesedb_libfdata.h" #include "libesedb_libfvalue.h" #include "libesedb_page.h" #include "libesedb_table_definition.h" #include "libesedb_value_data_handle.h" #include "esedb_page_values.h" /* Creates a data definition * Make sure the value data_definition is referencing, is set to NULL * Returns 1 if successful or -1 on error */ int libesedb_data_definition_initialize( libesedb_data_definition_t **data_definition, libcerror_error_t **error ) { static char *function = "libesedb_data_definition_initialize"; if( data_definition == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data definition.", function ); return( -1 ); } if( *data_definition != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid data definition value already set.", function ); return( -1 ); } *data_definition = memory_allocate_structure( libesedb_data_definition_t ); if( *data_definition == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data definition.", function ); goto on_error; } if( memory_set( *data_definition, 0, sizeof( libesedb_data_definition_t ) ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to clear data definition.", function ); goto on_error; } return( 1 ); on_error: if( *data_definition != NULL ) { memory_free( *data_definition ); *data_definition = NULL; } return( -1 ); } /* Frees a data definition * Returns 1 if successful or -1 on error */ int libesedb_data_definition_free( libesedb_data_definition_t **data_definition, libcerror_error_t **error ) { static char *function = "libesedb_data_definition_free"; if( data_definition == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data definition.", function ); return( -1 ); } if( *data_definition != NULL ) { memory_free( *data_definition ); *data_definition = NULL; } return( 1 ); } /* Reads the data * Returns 1 if successful or -1 on error */ int libesedb_data_definition_read_data( libesedb_data_definition_t *data_definition, libbfio_handle_t *file_io_handle, libesedb_io_handle_t *io_handle, libfdata_vector_t *pages_vector, libfcache_cache_t *pages_cache, uint8_t **data, size_t *data_size, libcerror_error_t **error ) { libesedb_page_t *page = NULL; libesedb_page_value_t *page_value = NULL; static char *function = "libesedb_data_definition_read_data"; off64_t element_data_offset = 0; uint16_t data_offset = 0; if( data_definition == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data definition.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data.", function ); return( -1 ); } if( data_size == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data size.", function ); return( -1 ); } if( libfdata_vector_get_element_value_at_offset( pages_vector, (intptr_t *) file_io_handle, (libfdata_cache_t *) pages_cache, data_definition->page_offset, &element_data_offset, (intptr_t **) &page, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve page: %" PRIu32 " at offset: 0x%08" PRIx64 ".", function, data_definition->page_number, data_definition->page_offset ); return( -1 ); } if( page == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing page.", function ); return( -1 ); } if( libesedb_page_get_value_by_index( page, data_definition->page_value_index, &page_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve page value: %" PRIu16 ".", function, data_definition->page_value_index ); return( -1 ); } if( page_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing page value: %" PRIu16 ".", function, data_definition->page_value_index ); return( -1 ); } if( page_value->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing page value data.", function ); return( -1 ); } data_offset = data_definition->data_offset - page_value->offset; if( ( data_definition->data_offset < page_value->offset ) || ( data_offset > page_value->size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data definition - data offset value out of bounds.", function ); return( -1 ); } *data = &( page_value->data[ data_offset ] ); *data_size = (size_t) ( page_value->size - data_offset ); return( 1 ); } /* Reads the record * Uses the definition data in the catalog definitions * Returns 1 if successful or -1 on error */ int libesedb_data_definition_read_record( libesedb_data_definition_t *data_definition, libbfio_handle_t *file_io_handle, libesedb_io_handle_t *io_handle, libfdata_vector_t *pages_vector, libfcache_cache_t *pages_cache, libesedb_table_definition_t *table_definition, libesedb_table_definition_t *template_table_definition, libcdata_array_t *values_array, uint8_t *record_flags, libcerror_error_t **error ) { libesedb_catalog_definition_t *column_catalog_definition = NULL; libesedb_page_t *page = NULL; libesedb_page_value_t *page_value = NULL; libfvalue_data_handle_t *value_data_handle = NULL; libfvalue_value_t *record_value = NULL; uint8_t *record_data = NULL; uint8_t *tagged_data_type_offset_data = NULL; static char *function = "libesedb_data_definition_read_record"; size_t record_data_size = 0; size_t remaining_definition_data_size = 0; off64_t element_data_offset = 0; uint16_t data_offset = 0; uint16_t fixed_size_data_type_value_offset = 0; uint16_t masked_previous_tagged_data_type_offset = 0; uint16_t masked_tagged_data_type_offset = 0; uint16_t previous_tagged_data_type_offset = 0; uint16_t previous_variable_size_data_type_size = 0; uint16_t tagged_data_type_identifier = 0; uint16_t tagged_data_type_offset = 0; uint16_t tagged_data_type_offset_bitmask = 0x3fff; uint16_t tagged_data_type_offset_data_size = 0; uint16_t tagged_data_type_size = 0; uint16_t tagged_data_type_value_offset = 0; uint16_t tagged_data_types_offset = 0; uint16_t variable_size_data_type_offset = 0; uint16_t variable_size_data_type_size = 0; uint16_t variable_size_data_type_value_offset = 0; uint16_t variable_size_data_type_value_size = 0; uint16_t variable_size_data_types_offset = 0; uint8_t current_variable_size_data_type = 0; uint8_t last_fixed_size_data_type = 0; uint8_t last_variable_size_data_type = 0; uint8_t number_of_variable_size_data_types = 0; uint8_t record_value_type = 0; uint8_t tagged_data_types_format = LIBESEDB_TAGGED_DATA_TYPES_FORMAT_INDEX; int column_catalog_definition_index = 0; int encoding = 0; int number_of_column_catalog_definitions = 0; int number_of_table_column_catalog_definitions = 0; int number_of_template_table_column_catalog_definitions = 0; int record_value_codepage = 0; if( data_definition == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data definition.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( table_definition == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid table definition.", function ); return( -1 ); } if( values_array == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid values array.", function ); return( -1 ); } if( record_flags == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid record flags.", function ); return( -1 ); } if( libfdata_vector_get_element_value_at_offset( pages_vector, (intptr_t *) file_io_handle, (libfdata_cache_t *) pages_cache, data_definition->page_offset, &element_data_offset, (intptr_t **) &page, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve page: %" PRIu32 " at offset: 0x%08" PRIx64 ".", function, data_definition->page_number, data_definition->page_offset ); goto on_error; } if( page == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing page.", function ); goto on_error; } if( libesedb_page_get_value_by_index( page, data_definition->page_value_index, &page_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve page value: %" PRIu16 ".", function, data_definition->page_value_index ); goto on_error; } if( page_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing page value: %" PRIu16 ".", function, data_definition->page_value_index ); goto on_error; } if( page_value->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing page value data.", function ); goto on_error; } data_offset = data_definition->data_offset - page_value->offset; if( ( data_definition->data_offset < page_value->offset ) || ( data_offset > page_value->size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data definition - data offset value out of bounds.", function ); goto on_error; } record_data = &( page_value->data[ data_offset ] ); record_data_size = page_value->size - data_offset; if( record_data_size < sizeof( esedb_data_definition_header_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid record data size value out of bounds.", function ); goto on_error; } if( ( io_handle->format_version == 0x620 ) && ( io_handle->format_revision <= 2 ) ) { tagged_data_types_format = LIBESEDB_TAGGED_DATA_TYPES_FORMAT_LINEAR; } if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER ) && ( io_handle->page_size >= 16384 ) ) { tagged_data_type_offset_bitmask = 0x7fff; } last_fixed_size_data_type = ( (esedb_data_definition_header_t *) record_data )->last_fixed_size_data_type; last_variable_size_data_type = ( (esedb_data_definition_header_t *) record_data )->last_variable_size_data_type; byte_stream_copy_to_uint16_little_endian( ( (esedb_data_definition_header_t *) record_data )->variable_size_data_types_offset, variable_size_data_types_offset ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: last fixed size data type\t\t\t: %" PRIu8 "\n", function, last_fixed_size_data_type ); libcnotify_printf( "%s: last variable size data type\t\t: %" PRIu8 "\n", function, last_variable_size_data_type ); libcnotify_printf( "%s: variable size data types offset\t\t: %" PRIu16 "\n", function, variable_size_data_types_offset ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( template_table_definition != NULL ) { if( libesedb_table_definition_get_number_of_column_catalog_definitions( template_table_definition, &number_of_template_table_column_catalog_definitions, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of template table column catalog definitions.", function ); goto on_error; } } if( libesedb_table_definition_get_number_of_column_catalog_definitions( table_definition, &number_of_table_column_catalog_definitions, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve number of table column catalog definitions.", function ); goto on_error; } number_of_column_catalog_definitions = number_of_table_column_catalog_definitions; if( template_table_definition != NULL ) { if( number_of_table_column_catalog_definitions > number_of_template_table_column_catalog_definitions ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid number of table column catalog definitions value exceeds number in template table.", function ); goto on_error; } number_of_column_catalog_definitions += number_of_template_table_column_catalog_definitions; } if( libcdata_array_resize( values_array, number_of_column_catalog_definitions, (int (*)(intptr_t **, libcerror_error_t **)) &libfvalue_value_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED, "%s: unable to resize values array.", function ); goto on_error; } if( last_variable_size_data_type > 127 ) { number_of_variable_size_data_types = last_variable_size_data_type - 127; } fixed_size_data_type_value_offset = (uint16_t) sizeof( esedb_data_definition_header_t ); current_variable_size_data_type = 127; variable_size_data_type_offset = variable_size_data_types_offset; variable_size_data_type_value_offset = variable_size_data_types_offset + ( number_of_variable_size_data_types * 2 ); for( column_catalog_definition_index = 0; column_catalog_definition_index < number_of_column_catalog_definitions; column_catalog_definition_index++ ) { if( ( template_table_definition != NULL ) && ( column_catalog_definition_index < number_of_template_table_column_catalog_definitions ) ) { if( libesedb_table_definition_get_column_catalog_definition_by_index( template_table_definition, column_catalog_definition_index, &column_catalog_definition, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve column catalog definition: %d from template table.", function, column_catalog_definition_index ); goto on_error; } } else { if( libesedb_table_definition_get_column_catalog_definition_by_index( table_definition, column_catalog_definition_index, &column_catalog_definition, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve column catalog definition: %d from table.", function, column_catalog_definition_index ); goto on_error; } } if( column_catalog_definition == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing column catalog definition: %d.", function, column_catalog_definition_index ); goto on_error; } if( column_catalog_definition->type != LIBESEDB_CATALOG_DEFINITION_TYPE_COLUMN ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported column catalog definition type: %" PRIu16 " for list element: %d.", function, column_catalog_definition->type, column_catalog_definition_index ); goto on_error; } if( ( template_table_definition != NULL ) && ( column_catalog_definition_index == number_of_template_table_column_catalog_definitions ) ) { if( column_catalog_definition->identifier != 256 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: only tagged data types supported in tables using a template table.", function ); goto on_error; } } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: column definition identifier\t\t: %03" PRIu32 "\n", function, column_catalog_definition->identifier ); libcnotify_printf( "%s: column definition name\t\t\t: %" PRIs_SYSTEM "\n", function, column_catalog_definition->name_string ); libcnotify_printf( "%s: column definition type\t\t\t: %s (%s)\n", function, libesedb_column_type_get_description( column_catalog_definition->column_type ), libesedb_column_type_get_identifier( column_catalog_definition->column_type ) ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ /* TODO refactor to value type */ switch( column_catalog_definition->column_type ) { case LIBESEDB_COLUMN_TYPE_NULL: /* JET_coltypNil seems to be able to contain data */ record_value_type = LIBFVALUE_VALUE_TYPE_BINARY_DATA; break; case LIBESEDB_COLUMN_TYPE_BOOLEAN: record_value_type = LIBFVALUE_VALUE_TYPE_BOOLEAN; break; case LIBESEDB_COLUMN_TYPE_INTEGER_8BIT_UNSIGNED: record_value_type = LIBFVALUE_VALUE_TYPE_UNSIGNED_INTEGER_8BIT; break; case LIBESEDB_COLUMN_TYPE_INTEGER_16BIT_SIGNED: record_value_type = LIBFVALUE_VALUE_TYPE_INTEGER_16BIT; break; case LIBESEDB_COLUMN_TYPE_INTEGER_16BIT_UNSIGNED: record_value_type = LIBFVALUE_VALUE_TYPE_UNSIGNED_INTEGER_16BIT; break; case LIBESEDB_COLUMN_TYPE_INTEGER_32BIT_SIGNED: record_value_type = LIBFVALUE_VALUE_TYPE_INTEGER_32BIT; break; case LIBESEDB_COLUMN_TYPE_INTEGER_32BIT_UNSIGNED: record_value_type = LIBFVALUE_VALUE_TYPE_UNSIGNED_INTEGER_32BIT; break; case LIBESEDB_COLUMN_TYPE_CURRENCY: case LIBESEDB_COLUMN_TYPE_INTEGER_64BIT_SIGNED: record_value_type = LIBFVALUE_VALUE_TYPE_INTEGER_64BIT; break; case LIBESEDB_COLUMN_TYPE_FLOAT_32BIT: record_value_type = LIBFVALUE_VALUE_TYPE_FLOATING_POINT_32BIT; break; case LIBESEDB_COLUMN_TYPE_DOUBLE_64BIT: record_value_type = LIBFVALUE_VALUE_TYPE_FLOATING_POINT_64BIT; break; case LIBESEDB_COLUMN_TYPE_DATE_TIME: record_value_type = LIBFVALUE_VALUE_TYPE_FILETIME; break; case LIBESEDB_COLUMN_TYPE_GUID: record_value_type = LIBFVALUE_VALUE_TYPE_GUID; break; case LIBESEDB_COLUMN_TYPE_BINARY_DATA: case LIBESEDB_COLUMN_TYPE_LARGE_BINARY_DATA: record_value_type = LIBFVALUE_VALUE_TYPE_BINARY_DATA; break; case LIBESEDB_COLUMN_TYPE_TEXT: case LIBESEDB_COLUMN_TYPE_LARGE_TEXT: record_value_type = LIBFVALUE_VALUE_TYPE_STRING_BYTE_STREAM; break; case LIBESEDB_COLUMN_TYPE_SUPER_LARGE_VALUE: /* TODO handle this value type */ record_value_type = LIBFVALUE_VALUE_TYPE_UNDEFINED; break; default: libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported column type: %" PRIu32 ".", function, column_catalog_definition->column_type ); goto on_error; } if( libfvalue_data_handle_initialize( &value_data_handle, (int (*)(libfvalue_data_handle_t *, const uint8_t *, size_t, int, uint32_t, libcerror_error_t **)) &libesedb_value_data_handle_read_value_entries, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create value data handle.", function ); goto on_error; } if( ( column_catalog_definition->column_type == LIBESEDB_COLUMN_TYPE_TEXT ) || ( column_catalog_definition->column_type == LIBESEDB_COLUMN_TYPE_LARGE_TEXT ) ) { record_value_codepage = (int) column_catalog_definition->codepage; /* If the codepage is not set use the default codepage */ if( record_value_codepage == 0 ) { record_value_codepage = io_handle->ascii_codepage; } /* Codepage 1200 in the ESE database format is not strict UTF-16 little-endian * it can be used for ASCII strings as well. */ if( record_value_codepage == 1200 ) { record_value_codepage = LIBFVALUE_CODEPAGE_1200_MIXED; } encoding = record_value_codepage; } else { encoding = LIBFVALUE_ENDIAN_LITTLE; } if( column_catalog_definition->identifier <= 127 ) { if( column_catalog_definition->identifier <= last_fixed_size_data_type ) { if( column_catalog_definition->size > ( record_data_size - fixed_size_data_type_value_offset ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data definition - size value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: (%03" PRIu32 ") fixed size data type size\t\t: %" PRIu32 "\n", function, column_catalog_definition->identifier, column_catalog_definition->size ); libcnotify_print_data( &( record_data[ fixed_size_data_type_value_offset ] ), column_catalog_definition->size, 0 ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( libfvalue_data_handle_set_data( value_data_handle, &( record_data[ fixed_size_data_type_value_offset ] ), column_catalog_definition->size, encoding, LIBFVALUE_VALUE_DATA_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set data in fixed size data type definition.", function ); goto on_error; } if( column_catalog_definition->size > (uint32_t) UINT16_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid common catalog definition size value exceeds maximum.", function ); goto on_error; } fixed_size_data_type_value_offset += (uint16_t) column_catalog_definition->size; } } else if( current_variable_size_data_type < last_variable_size_data_type ) { while( current_variable_size_data_type < column_catalog_definition->identifier ) { if( variable_size_data_type_offset > ( record_data_size - 2 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid variable size data type offset value out of bounds.", function ); goto on_error; } byte_stream_copy_to_uint16_little_endian( &( record_data[ variable_size_data_type_offset ] ), variable_size_data_type_size ); variable_size_data_type_offset += 2; current_variable_size_data_type++; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: (%03" PRIu16 ") variable size data type size\t: 0x%04" PRIx16 " (%" PRIu16 ")\n", function, current_variable_size_data_type, variable_size_data_type_size, ( ( variable_size_data_type_size & 0x8000 ) != 0 ) ? 0 : ( variable_size_data_type_size & 0x7fff ) - previous_variable_size_data_type_size ); } #endif if( current_variable_size_data_type == column_catalog_definition->identifier ) { /* The MSB signifies that the variable size data type is empty */ if( ( variable_size_data_type_size & 0x8000 ) == 0 ) { if( variable_size_data_type_size < previous_variable_size_data_type_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid variable size data type size value out of bounds.", function ); goto on_error; } variable_size_data_type_value_size = variable_size_data_type_size - previous_variable_size_data_type_size; if( ( variable_size_data_type_value_size > record_data_size ) || ( variable_size_data_type_value_offset > ( record_data_size - variable_size_data_type_value_size ) ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid variable size data type value size value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: (%03" PRIu32 ") variable size data type:\n", function, column_catalog_definition->identifier ); libcnotify_print_data( &( record_data[ variable_size_data_type_value_offset ] ), variable_size_data_type_value_size, 0 ); } #endif if( libfvalue_data_handle_set_data( value_data_handle, &( record_data[ variable_size_data_type_value_offset ] ), variable_size_data_type_value_size, encoding, LIBFVALUE_VALUE_DATA_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set data in variable size data type definition.", function ); goto on_error; } variable_size_data_type_value_offset += variable_size_data_type_value_size; previous_variable_size_data_type_size = variable_size_data_type_size; } #if defined( HAVE_DEBUG_OUTPUT ) else if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: (%03" PRIu32 ") variable size data type\t\t: \n", function, column_catalog_definition->identifier ); } #endif } if( current_variable_size_data_type >= last_variable_size_data_type ) { break; } } } else { if( tagged_data_types_format == LIBESEDB_TAGGED_DATA_TYPES_FORMAT_LINEAR ) { if( tagged_data_types_offset == 0 ) { tagged_data_types_offset = variable_size_data_type_value_offset; tagged_data_type_value_offset = variable_size_data_type_value_offset; remaining_definition_data_size = record_data_size - (size_t) tagged_data_types_offset; byte_stream_copy_to_uint16_little_endian( &( record_data[ tagged_data_type_value_offset ] ), tagged_data_type_identifier ); tagged_data_type_value_offset += 2; byte_stream_copy_to_uint16_little_endian( &( record_data[ tagged_data_type_value_offset ] ), tagged_data_type_size ); tagged_data_type_value_offset += 2; remaining_definition_data_size -= 4; } if( ( remaining_definition_data_size > 0 ) && ( column_catalog_definition->identifier == tagged_data_type_identifier ) ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: (%03" PRIu16 ") tagged data type identifier\t\t: %" PRIu16 "\n", function, column_catalog_definition->identifier, tagged_data_type_identifier ); libcnotify_printf( "%s: (%03" PRIu16 ") tagged data type size\t\t: 0x%04" PRIx16 " (%" PRIu16 ")\n", function, column_catalog_definition->identifier, tagged_data_type_size, tagged_data_type_size & 0x5fff ); } #endif if( ( tagged_data_type_size & 0x8000 ) != 0 ) { if( tagged_data_type_value_offset >= record_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid tagged data type offset value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: (%03" PRIu16 ") tagged data type flags\t\t: 0x%02" PRIx8 "\n", function, column_catalog_definition->identifier, record_data[ tagged_data_type_value_offset ] ); libesedb_debug_print_tagged_data_type_flags( record_data[ tagged_data_type_value_offset ] ); libcnotify_printf( "\n" ); } #endif if( libfvalue_data_handle_set_data_flags( value_data_handle, (uint32_t) record_data[ tagged_data_type_value_offset ], error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set tagged data type flags in tagged data type definition.", function ); goto on_error; } tagged_data_type_value_offset += 1; tagged_data_type_size = ( tagged_data_type_size & 0x5fff ) - 1; remaining_definition_data_size -= 1; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( tagged_data_type_size > 0 ) { libcnotify_printf( "%s: (%03" PRIu16 ") tagged data type:\n", function, column_catalog_definition->identifier ); if( tagged_data_type_value_offset < record_data_size ) { libcnotify_print_data( &( record_data[ tagged_data_type_value_offset ] ), tagged_data_type_size, 0 ); } else { libcnotify_printf( "\n\n" ); } } else { libcnotify_printf( "%s: (%03" PRIu32 ") tagged data type\t\t\t: \n", function, column_catalog_definition->identifier ); } } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ if( tagged_data_type_size > 0 ) { if( tagged_data_type_value_offset >= record_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid tagged data type offset value out of bounds.", function ); goto on_error; } if( tagged_data_type_size > remaining_definition_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid tagged data type size value exceeds remaining data size.", function ); goto on_error; } if( libfvalue_data_handle_set_data( value_data_handle, &( record_data[ tagged_data_type_value_offset ] ), tagged_data_type_size, encoding, LIBFVALUE_VALUE_DATA_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set data in tagged data type definition.", function ); goto on_error; } remaining_definition_data_size -= tagged_data_type_size; } if( remaining_definition_data_size > 0 ) { if( tagged_data_type_value_offset >= record_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid tagged data type offset value out of bounds.", function ); goto on_error; } byte_stream_copy_to_uint16_little_endian( &( record_data[ tagged_data_type_value_offset ] ), tagged_data_type_identifier ); tagged_data_type_value_offset += 2; byte_stream_copy_to_uint16_little_endian( &( record_data[ tagged_data_type_value_offset ] ), tagged_data_type_size ); tagged_data_type_value_offset += 2; remaining_definition_data_size -= 4; } } } else if( tagged_data_types_format == LIBESEDB_TAGGED_DATA_TYPES_FORMAT_INDEX ) { if( tagged_data_types_offset == 0 ) { tagged_data_types_offset = variable_size_data_type_value_offset; /* Note that offset is allowed to be equal to the record data size here */ if( tagged_data_types_offset > record_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid tagged data types offset value out of bounds.", function ); goto on_error; } tagged_data_type_offset_data = &( record_data[ tagged_data_types_offset ] ); remaining_definition_data_size = record_data_size - (size_t) tagged_data_types_offset; if( remaining_definition_data_size > 0 ) { if( record_data_size < 4 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid tagged data types offset data size value out of bounds.", function ); goto on_error; } byte_stream_copy_to_uint16_little_endian( tagged_data_type_offset_data, tagged_data_type_identifier ); tagged_data_type_offset_data += 2; byte_stream_copy_to_uint16_little_endian( tagged_data_type_offset_data, tagged_data_type_offset ); tagged_data_type_offset_data += 2; if( tagged_data_type_offset == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid tagged data type offset value out of bounds.", function ); goto on_error; } tagged_data_type_offset_data_size = ( tagged_data_type_offset & 0x3fff ) - 4; remaining_definition_data_size -= 4; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: tagged data type offset data size\t\t: %" PRIu16 "\n", function, tagged_data_type_offset_data_size ); libcnotify_printf( "%s: tagged data type offset data:\n", function ); libcnotify_print_data( tagged_data_type_offset_data, tagged_data_type_offset_data_size + 4, 0 ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ } } if( ( remaining_definition_data_size > 0 ) && ( column_catalog_definition->identifier == tagged_data_type_identifier ) ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: (%03" PRIu16 ") tagged data type identifier\t\t: %" PRIu16 "\n", function, column_catalog_definition->identifier, tagged_data_type_identifier ); libcnotify_printf( "%s: (%03" PRIu16 ") tagged data type offset\t\t: 0x%04" PRIx16 " (%" PRIu16 ")\n", function, column_catalog_definition->identifier, tagged_data_type_offset, tagged_data_type_offset & tagged_data_type_offset_bitmask ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ previous_tagged_data_type_offset = tagged_data_type_offset; if( tagged_data_type_offset_data_size > 0 ) { if( tagged_data_type_offset_data_size < 4 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid tagged data types offset data size value out of bounds.", function ); goto on_error; } byte_stream_copy_to_uint16_little_endian( tagged_data_type_offset_data, tagged_data_type_identifier ); tagged_data_type_offset_data += 2; byte_stream_copy_to_uint16_little_endian( tagged_data_type_offset_data, tagged_data_type_offset ); tagged_data_type_offset_data += 2; tagged_data_type_offset_data_size -= 4; remaining_definition_data_size -= 4; } masked_previous_tagged_data_type_offset = previous_tagged_data_type_offset & tagged_data_type_offset_bitmask; masked_tagged_data_type_offset = tagged_data_type_offset & tagged_data_type_offset_bitmask; if( masked_previous_tagged_data_type_offset > masked_tagged_data_type_offset ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid tagged data type offset value exceeds next tagged data type offset.", function ); goto on_error; } if( masked_tagged_data_type_offset > masked_previous_tagged_data_type_offset ) { tagged_data_type_size = masked_tagged_data_type_offset - masked_previous_tagged_data_type_offset; } else { tagged_data_type_size = (uint16_t) remaining_definition_data_size; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: (%03" PRIu16 ") tagged data type size\t\t: %" PRIu16 "\n", function, column_catalog_definition->identifier, tagged_data_type_size ); } #endif tagged_data_type_value_offset = tagged_data_types_offset + masked_previous_tagged_data_type_offset; if( tagged_data_type_size > 0 ) { if( tagged_data_type_size > remaining_definition_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid tagged data type size value exceeds remaining data size.", function ); goto on_error; } remaining_definition_data_size -= tagged_data_type_size; if( ( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER ) && ( io_handle->page_size >= 16384 ) ) || ( ( previous_tagged_data_type_offset & 0x4000 ) != 0 ) ) { if( tagged_data_type_value_offset >= record_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid tagged data type offset value out of bounds.", function ); goto on_error; } if( libfvalue_data_handle_set_data_flags( value_data_handle, (uint32_t) record_data[ tagged_data_type_value_offset ], error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set tagged data type flags in tagged data type definition.", function ); goto on_error; } tagged_data_type_value_offset += 1; tagged_data_type_size -= 1; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: (%03" PRIu16 ") tagged data type:\n", function, column_catalog_definition->identifier ); if( tagged_data_type_value_offset < record_data_size ) { libcnotify_print_data( &( record_data[ tagged_data_type_value_offset ] ), tagged_data_type_size, 0 ); } else { libcnotify_printf( "\n\n" ); } } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ } #if defined( HAVE_DEBUG_OUTPUT ) /* TODO are zero size tagged data type values handled correctly? */ else if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: (%03" PRIu32 ") tagged data type\t\t\t: \n", function, column_catalog_definition->identifier ); } #endif if( tagged_data_type_size > 0 ) { if( tagged_data_type_value_offset >= record_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid tagged data type offset value out of bounds.", function ); goto on_error; } if( tagged_data_type_size > ( record_data_size - tagged_data_type_value_offset ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid tagged data type size value out of bounds.", function ); goto on_error; } if( libfvalue_data_handle_set_data( value_data_handle, &( record_data[ tagged_data_type_value_offset ] ), tagged_data_type_size, encoding, LIBFVALUE_VALUE_DATA_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set data in tagged data type definition.", function ); goto on_error; } } } } } if( libfvalue_value_type_initialize_with_data_handle( &record_value, record_value_type, value_data_handle, LIBFVALUE_VALUE_FLAG_DATA_HANDLE_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create record value.", function ); goto on_error; } value_data_handle = NULL; if( libcdata_array_set_entry_by_index( values_array, column_catalog_definition_index, (intptr_t *) record_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_SET_FAILED, "%s: unable to set data type definition: %d.", function, column_catalog_definition_index ); goto on_error; } record_value = NULL; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( fixed_size_data_type_value_offset < variable_size_data_types_offset ) { libcnotify_printf( "%s: fixed size data types trailing data:\n", function ); libcnotify_print_data( &( record_data[ fixed_size_data_type_value_offset ] ), variable_size_data_types_offset - fixed_size_data_type_value_offset, 0 ); } libcnotify_printf( "\n" ); } #endif /* defined( HAVE_DEBUG_OUTPUT ) */ return( 1 ); on_error: if( record_value != NULL ) { libfvalue_value_free( &record_value, NULL ); } if( value_data_handle != NULL ) { libfvalue_data_handle_free( &value_data_handle, NULL ); } return( -1 ); } /* Reads the long value * Returns 1 if successful or -1 on error */ int libesedb_data_definition_read_long_value( libesedb_data_definition_t *data_definition, libbfio_handle_t *file_io_handle, libfdata_vector_t *pages_vector, libfcache_cache_t *pages_cache, libcerror_error_t **error ) { libesedb_page_t *page = NULL; libesedb_page_value_t *page_value = NULL; uint8_t *long_value_data = NULL; static char *function = "libesedb_data_definition_read_long_value"; size_t long_value_data_size = 0; off64_t element_data_offset = 0; uint32_t value_32bit = 0; uint16_t data_offset = 0; if( data_definition == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data definition.", function ); return( -1 ); } if( libfdata_vector_get_element_value_at_offset( pages_vector, (intptr_t *) file_io_handle, (libfdata_cache_t *) pages_cache, data_definition->page_offset, &element_data_offset, (intptr_t **) &page, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve page: %" PRIu32 " at offset: 0x%08" PRIx64 ".", function, data_definition->page_number, data_definition->page_offset ); return( -1 ); } if( page == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing page.", function ); return( -1 ); } if( libesedb_page_get_value_by_index( page, data_definition->page_value_index, &page_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve page value: %" PRIu16 ".", function, data_definition->page_value_index ); return( -1 ); } if( page_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing page value: %" PRIu16 ".", function, data_definition->page_value_index ); return( -1 ); } if( page_value->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing page value data.", function ); return( -1 ); } data_offset = data_definition->data_offset - page_value->offset; if( ( data_definition->data_offset < page_value->offset ) || ( data_offset > page_value->size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data definition - data offset value out of bounds.", function ); return( -1 ); } long_value_data = &( page_value->data[ data_offset ] ); long_value_data_size = page_value->size - data_offset; if( long_value_data_size != 8 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported long values data size: %" PRIzd ".", function, long_value_data_size ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: long value data:\n", function ); libcnotify_print_data( long_value_data, long_value_data_size, 0 ); } #endif byte_stream_copy_to_uint16_little_endian( long_value_data, value_32bit ); long_value_data += 4; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unknown1\t\t\t\t: %" PRIu32 "\n", function, value_32bit ); } #endif byte_stream_copy_to_uint16_little_endian( long_value_data, value_32bit ); long_value_data += 4; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: last segment offset\t\t\t: %" PRIu32 "\n", function, value_32bit ); libcnotify_printf( "\n" ); } #endif return( 1 ); } /* Reads the long value segment * Returns 1 if successful or -1 on error */ int libesedb_data_definition_read_long_value_segment( libesedb_data_definition_t *data_definition, libbfio_handle_t *file_io_handle, libesedb_io_handle_t *io_handle, libfdata_vector_t *pages_vector, libfcache_cache_t *pages_cache, uint32_t long_value_segment_offset, libfdata_list_t *data_segments_list, libcerror_error_t **error ) { libesedb_page_t *page = NULL; libesedb_page_value_t *page_value = NULL; static char *function = "libesedb_data_definition_read_long_value_segment"; off64_t element_data_offset = 0; off64_t long_value_segment_data_offset = 0; size64_t data_size = 0; size_t long_value_segment_data_size = 0; uint16_t data_offset = 0; int element_index = 0; if( data_definition == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data definition.", function ); return( -1 ); } if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); return( -1 ); } if( libfdata_vector_get_element_value_at_offset( pages_vector, (intptr_t *) file_io_handle, (libfdata_cache_t *) pages_cache, data_definition->page_offset, &element_data_offset, (intptr_t **) &page, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve page: %" PRIu32 " at offset: 0x%08" PRIx64 ".", function, data_definition->page_number, data_definition->page_offset ); return( -1 ); } if( page == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing page.", function ); return( -1 ); } if( libesedb_page_get_value_by_index( page, data_definition->page_value_index, &page_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve page value: %" PRIu16 ".", function, data_definition->page_value_index ); return( -1 ); } if( page_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing page value: %" PRIu16 ".", function, data_definition->page_value_index ); return( -1 ); } if( page_value->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: missing page value data.", function ); return( -1 ); } data_offset = data_definition->data_offset - page_value->offset; if( ( data_definition->data_offset < page_value->offset ) || ( data_offset > page_value->size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid data definition - data offset value out of bounds.", function ); return( -1 ); } long_value_segment_data_size = page_value->size - data_offset; /* Note that the data stream will point to the file offset * io_handle->pages_data_offset contains the offset relative from the start of the file to the page data * data_definition->page_offset contains the offset relative from the start of the page data * data_definition->data_offset contains the offset relative from the start of the page */ long_value_segment_data_offset = io_handle->pages_data_offset + data_definition->page_offset + data_definition->data_offset; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: long value segment with offset: %" PRIu32 " has data at offset: %" PRIi64 " (0x%08" PRIx64 ") of size: %" PRIzd "\n", function, long_value_segment_offset, long_value_segment_data_offset, long_value_segment_data_offset, long_value_segment_data_size ); libcnotify_printf( "\n" ); } #endif if( libfdata_list_get_size( data_segments_list, &data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve size of data segments list.", function ); return( -1 ); } if( long_value_segment_offset != (off64_t) data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported long value segment offset: %" PRIi64 " value must match end of previous segment: %" PRIzd ".", function, long_value_segment_offset, data_size ); return( -1 ); } if( libfdata_list_append_element( data_segments_list, &element_index, 0, long_value_segment_data_offset, (size64_t) long_value_segment_data_size, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append long value segment at offset: 0x%08" PRIx64 " to data segments list.", function, long_value_segment_offset ); return( -1 ); } return( 1 ); }