/* Reads a link target identifier * Returns the number of bytes read if successful or -1 on error */ ssize_t liblnk_link_target_identifier_read( liblnk_link_target_identifier_t *link_target_identifier, liblnk_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, off64_t file_offset, libcerror_error_t **error ) { uint8_t size_data[ 2 ]; static char *function = "liblnk_link_target_identifier_read"; ssize_t read_count = 0; #if defined( HAVE_DEBUG_OUTPUT ) libfwsi_item_list_t *shell_item_list = NULL; size_t shell_item_list_data_size = 0; #endif if( link_target_identifier == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid link target identifier.", function ); return( -1 ); } if( link_target_identifier->data != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid link target identifier - data value already set.", 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 defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading link target identifier at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, file_offset, file_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek link target identifier offset: %" PRIi64 ".", function, file_offset ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, size_data, 2, error ); if( read_count != (ssize_t) 2 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read link target identifier size.", function ); goto on_error; } byte_stream_copy_to_uint16_little_endian( size_data, link_target_identifier->data_size ) link_target_identifier->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * link_target_identifier->data_size ); if( link_target_identifier->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create link target identifier data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, link_target_identifier->data, link_target_identifier->data_size, error ); if( read_count != (ssize_t) link_target_identifier->data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read link target identifier data.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfwsi_item_list_initialize( &shell_item_list, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create shell item list.", function ); goto on_error; } if( libfwsi_item_list_copy_from_byte_stream( shell_item_list, link_target_identifier->data, link_target_identifier->data_size, io_handle->ascii_codepage, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy byte stream to shell item list.", function ); goto on_error; } if( libfwsi_item_list_get_data_size( shell_item_list, &shell_item_list_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve shell item list data size.", function ); goto on_error; } if( libfwsi_item_list_free( &shell_item_list, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free shell item list.", function ); goto on_error; } } #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( shell_item_list_data_size < link_target_identifier->data_size ) { libcnotify_printf( "%s: trailing data:\n", function ); libcnotify_print_data( &( link_target_identifier->data[ shell_item_list_data_size ] ), link_target_identifier->data_size - shell_item_list_data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } } #endif return( (ssize_t) ( link_target_identifier->data_size + 2 ) ); on_error: #if defined( HAVE_DEBUG_OUTPUT ) if( shell_item_list != NULL ) { libfwsi_item_list_free( &shell_item_list, NULL ); } #endif if( link_target_identifier->data != NULL ) { memory_free( link_target_identifier->data ); link_target_identifier->data = NULL; } link_target_identifier->data_size = 0; return( -1 ); }
/* Reads cluster block * Returns 1 if successful or -1 on error */ int libqcow_cluster_block_read( libqcow_cluster_block_t *cluster_block, libbfio_handle_t *file_io_handle, off64_t cluster_block_offset, libcerror_error_t **error ) { static char *function = "libqcow_cluster_block_read"; ssize_t read_count = 0; if( cluster_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid cluster block.", function ); return( -1 ); } if( cluster_block->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid cluster block - missing data.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading cluster block at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, cluster_block_offset, cluster_block_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, cluster_block_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek cluster block offset: %" PRIi64 " (0x%08" PRIx64 ").", function, cluster_block_offset, cluster_block_offset ); return( -1 ); } read_count = libbfio_handle_read_buffer( file_io_handle, cluster_block->data, cluster_block->data_size, error ); if( read_count != (ssize_t) cluster_block->data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read cluster block.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: cluster block:\n", function ); libcnotify_print_data( cluster_block->data, cluster_block->data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif return( 1 ); }
/* Reads the debug data * Returns 1 if successful or -1 on error */ int libexe_debug_data_read( libexe_debug_data_t *debug_data, libbfio_handle_t *file_io_handle, uint32_t file_offset, uint32_t size, libcerror_error_t **error ) { uint8_t *data = NULL; static char *function = "libexe_debug_data_read"; size_t read_count = 0; if( debug_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid debug data.", function ); return( -1 ); } #if SIZEOF_SIZE_T <= 4 if( size > (uint32_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); return( -1 ); } #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading debug data at offset: %" PRIu32 " (0x%08" PRIx32 ")\n", function, file_offset, file_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, (off64_t) file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek debug data offset: %" PRIx32 ".", function, file_offset ); goto on_error; } data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * size ); if( data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create debug data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, data, size, error ); if( read_count != (ssize_t) size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read debug data.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: debug data:\n", function ); libcnotify_print_data( data, (size_t) size, 0 ); } #endif /* TODO extract values */ memory_free( data ); return( 1 ); on_error: if( data != NULL ) { memory_free( data ); } return( -1 ); }
/* Reads a redirected * Returns 1 if successful or -1 on error */ int libmsiecf_redirected_values_read( libmsiecf_redirected_values_t *redirected_values, libmsiecf_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, off64_t redirected_offset, size32_t record_size, uint8_t item_flags, libcerror_error_t **error ) { uint8_t *redr_record_data = NULL; static char *function = "libmsiecf_redirected_values_read"; ssize_t read_count = 0; ssize_t value_size = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint32_t value_32bit = 0; #endif if( redirected_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid redirected values.", function ); return( -1 ); } if( record_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS, "%s: invalid record size value zero or less.", function ); return( -1 ); } #if SIZEOF_SIZE_T <= 4 if( record_size > (size32_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid record size value exceeds maximum.", function ); return( -1 ); } #endif if( ( record_size % 8 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported REDR record size.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading REDR record at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, redirected_offset, redirected_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, redirected_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek REDR record offset: %" PRIi64 ".", function, redirected_offset ); goto on_error; } redr_record_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * record_size ); if( redr_record_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create REDR record data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, redr_record_data, record_size, error ); if( read_count != (ssize_t) record_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read REDR record data.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: REDR record data:\n", function ); libcnotify_print_data( redr_record_data, record_size, 0 ); } #endif if( memory_compare( ( (msiecf_redr_record_header_t *) redr_record_data )->signature, "REDR", 4 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported signature.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: signature\t\t\t\t: %c%c%c%c\n", function, ( (msiecf_redr_record_header_t *) redr_record_data )->signature[ 0 ], ( (msiecf_redr_record_header_t *) redr_record_data )->signature[ 1 ], ( (msiecf_redr_record_header_t *) redr_record_data )->signature[ 2 ], ( (msiecf_redr_record_header_t *) redr_record_data )->signature[ 3 ] ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_redr_record_header_t *) redr_record_data )->number_of_blocks, value_32bit ); libcnotify_printf( "%s: number of blocks\t\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_redr_record_header_t *) redr_record_data )->unknown1, value_32bit ); libcnotify_printf( "%s: unknown1\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_redr_record_header_t *) redr_record_data )->unknown2, value_32bit ); libcnotify_printf( "%s: unknown2\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); } #endif if( libfvalue_value_type_initialize( &( redirected_values->location ), LIBFVALUE_VALUE_TYPE_STRING_BYTE_STREAM, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create location value.", function ); goto on_error; } value_size = libfvalue_value_type_set_data_string( redirected_values->location, &( redr_record_data[ 16 ] ), record_size - 16, io_handle->ascii_codepage, LIBFVALUE_VALUE_DATA_FLAG_MANAGED, error ); if( value_size == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set data of location value.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: location\t\t\t\t: ", function ); if( libfvalue_value_print( redirected_values->location, 0, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print location value.", function ); goto on_error; } libcnotify_printf( "\n" ); if( libmsiecf_hash_calculate( &value_32bit, &( redr_record_data[ 16 ] ), record_size - 16, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to calculate location hash.", function ); goto on_error; } libcnotify_printf( "%s: hash value\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); } #endif if( ( redr_record_data[ 16 + value_size - 1 ] != 0 ) && ( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported unterminated location string.", function ); goto on_error; } memory_free( redr_record_data ); redr_record_data = NULL; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n" ); } #endif return( 1 ); on_error: if( redirected_values->location != NULL ) { libfvalue_value_free( &( redirected_values->location ), NULL ); } if( redr_record_data != NULL ) { memory_free( redr_record_data ); } return( -1 ); }
/* Reads an index node * Returns 1 if successful or -1 on error */ int libpff_index_node_read( libpff_index_node_t *index_node, libpff_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, off64_t node_offset, libcerror_error_t **error ) { uint8_t *index_node_footer_data = NULL; static char *function = "libpff_index_node_read"; ssize_t read_count = 0; uint32_t calculated_checksum = 0; uint32_t stored_checksum = 0; uint8_t calculated_entry_size = 0; uint8_t calculated_maximum_number_of_entries = 0; uint8_t index_node_type_copy = 0; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint8_t *index_node_entry_data = NULL; uint64_t value_64bit = 0; uint32_t value_32bit = 0; uint16_t entry_index = 0; uint16_t index_node_entry_data_size = 0; uint16_t value_16bit = 0; #endif if( index_node == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid index node.", function ); return( -1 ); } if( index_node->data != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid index node - data already set.", 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( ( io_handle->file_type != LIBPFF_FILE_TYPE_32BIT ) && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT ) && ( io_handle->file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported file type.", function ); return( -1 ); } if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { index_node->data_size = 512; index_node->maximum_entries_data_size = 512 - sizeof( pff_index_node_32bit_footer_t ); } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) { index_node->data_size = 512; index_node->maximum_entries_data_size = 512 - sizeof( pff_index_node_64bit_footer_t ); } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) { index_node->data_size = 4096; index_node->maximum_entries_data_size = 4096 - sizeof( pff_index_node_64bit_4k_page_footer_t ); } index_node->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * index_node->data_size ); if( index_node->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create index node data.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading index node data at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, node_offset, node_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, node_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek node offset: %" PRIi64 ".", function, node_offset ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, index_node->data, index_node->data_size, error ); if( read_count != (ssize_t) index_node->data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read index node data.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: index node data:\n", function ); libcnotify_print_data( index_node->data, index_node->data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif index_node_footer_data = &( index_node->data[ index_node->maximum_entries_data_size ] ); if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { index_node->type = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->type; index_node_type_copy = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->type_copy; byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->back_pointer, index_node->back_pointer ); byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->checksum, stored_checksum ); index_node->number_of_entries = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->number_of_entries; index_node->maximum_number_of_entries = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->maximum_number_of_entries; index_node->entry_size = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->entry_size; index_node->level = ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->level; if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR ) && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) ) { calculated_entry_size = 16; calculated_maximum_number_of_entries = 496 / 16; } else { calculated_entry_size = 12; calculated_maximum_number_of_entries = 496 / 12; } } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) { index_node->type = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->type; index_node_type_copy = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->type_copy; byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->checksum, stored_checksum ); byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->back_pointer, index_node->back_pointer ); index_node->number_of_entries = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->number_of_entries; index_node->maximum_number_of_entries = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->maximum_number_of_entries; index_node->entry_size = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->entry_size; index_node->level = ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->level; if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR ) && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) ) { calculated_entry_size = 32; calculated_maximum_number_of_entries = 488 / 32; } else { calculated_entry_size = 24; calculated_maximum_number_of_entries = 488 / 24; } } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) { index_node->type = ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->type; index_node_type_copy = ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->type_copy; byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->checksum, stored_checksum ); byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->back_pointer, index_node->back_pointer ); byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->number_of_entries, index_node->number_of_entries ); byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->maximum_number_of_entries, index_node->maximum_number_of_entries ); index_node->entry_size = ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->entry_size; index_node->level = ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->level; if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR ) && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) ) { calculated_entry_size = 32; calculated_maximum_number_of_entries = 4056 / 32; } else { calculated_entry_size = 24; calculated_maximum_number_of_entries = 4056 / 24; } } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: number of entries\t\t\t\t: %" PRIu16 "\n", function, index_node->number_of_entries ); libcnotify_printf( "%s: maximum number of entries\t\t\t: %" PRIu16 "\n", function, index_node->maximum_number_of_entries ); libcnotify_printf( "%s: entry size\t\t\t\t\t: %" PRIu8 "\n", function, index_node->entry_size ); libcnotify_printf( "%s: node level\t\t\t\t\t: %" PRIu8 "\n", function, index_node->level ); if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) { libcnotify_printf( "%s: padding:\n", function ); libcnotify_print_data( ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->padding1, 4, 0 ); } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) { libcnotify_printf( "%s: padding:\n", function ); libcnotify_print_data( ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->padding1, 10, 0 ); } libcnotify_printf( "%s: index node type\t\t\t\t\t: 0x%02" PRIx8 "\n", function, index_node->type ); libcnotify_printf( "%s: index node type copy\t\t\t\t: 0x%02" PRIx8 "\n", function, index_node_type_copy ); if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_32bit_footer_t *) index_node_footer_data )->signature, value_16bit ); libcnotify_printf( "%s: signature\t\t\t\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "%s: back pointer\t\t\t\t\t: 0x%08" PRIx64 "\n", function, index_node->back_pointer ); libcnotify_printf( "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", function, stored_checksum ); } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) { byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_64bit_footer_t *) index_node_footer_data )->signature, value_16bit ); libcnotify_printf( "%s: signature\t\t\t\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", function, stored_checksum ); libcnotify_printf( "%s: back pointer\t\t\t\t\t: 0x%08" PRIx64 "\n", function, index_node->back_pointer ); } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) { byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->signature, value_16bit ); libcnotify_printf( "%s: signature\t\t\t\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", function, stored_checksum ); libcnotify_printf( "%s: back pointer\t\t\t\t\t: 0x%08" PRIx64 "\n", function, index_node->back_pointer ); byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_64bit_4k_page_footer_t *) index_node_footer_data )->unknown1, value_64bit ); libcnotify_printf( "%s: unknown1\t\t\t\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); } libcnotify_printf( "\n" ); } #endif if( index_node->type != index_node_type_copy ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: mismatch in index node type (0x%02" PRIx8 " != 0x%02" PRIx8 ").\n", function, index_node->type, index_node_type_copy ); } #endif if( ( index_node->type != LIBPFF_INDEX_TYPE_DESCRIPTOR ) && ( index_node->type != LIBPFF_INDEX_TYPE_OFFSET ) && ( ( index_node_type_copy == LIBPFF_INDEX_TYPE_DESCRIPTOR ) || ( index_node_type_copy == LIBPFF_INDEX_TYPE_OFFSET ) ) ) { index_node->type = index_node_type_copy; } } if( ( index_node->type != LIBPFF_INDEX_TYPE_DESCRIPTOR ) && ( index_node->type != LIBPFF_INDEX_TYPE_OFFSET ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported index node type: 0x%02" PRIx8 ".", function, index_node->type ); goto on_error; } if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { result = libfmapi_checksum_calculate_weak_crc32( &calculated_checksum, index_node->data, 500, 0, error ); } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) { result = libfmapi_checksum_calculate_weak_crc32( &calculated_checksum, index_node->data, 496, 0, error ); } else if( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) { result = libfmapi_checksum_calculate_weak_crc32( &calculated_checksum, index_node->data, 4072, 0, error ); } if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to calculate weak CRC-32.", function ); goto on_error; } if( stored_checksum != calculated_checksum ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: mismatch in checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n", function, stored_checksum, calculated_checksum ); } #endif /* TODO smart error handling */ } if( ( index_node->entry_size != 0 ) && ( index_node->entry_size != calculated_entry_size ) ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: entry size mismatch (calculated: %" PRIu8 ", stored: %" PRIu8 ").\n", function, calculated_entry_size, index_node->entry_size ); } #endif index_node->entry_size = calculated_entry_size; } if( ( index_node->maximum_number_of_entries != 0 ) && ( index_node->maximum_number_of_entries != calculated_maximum_number_of_entries ) ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: maximum number of entries mismatch (calculated: %" PRIu8 ", stored: %" PRIu8 ").\n", function, calculated_maximum_number_of_entries, index_node->maximum_number_of_entries ); } #endif index_node->maximum_number_of_entries = calculated_maximum_number_of_entries; } if( index_node->number_of_entries > index_node->maximum_number_of_entries ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: number of entries: %" PRIu8 ", exceeds maximum: %" PRIu8 ".", function, index_node->number_of_entries, index_node->maximum_number_of_entries ); } #endif index_node->number_of_entries = index_node->maximum_number_of_entries; } if( ( (uint16_t) index_node->number_of_entries * (uint16_t) index_node->entry_size ) > index_node->maximum_entries_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: size of entries: %" PRIu16 ", exceeds maximum: %" PRIu16 ".", function, index_node->number_of_entries * index_node->entry_size, index_node->maximum_entries_data_size ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { index_node_entry_data = index_node->data; index_node_entry_data_size = index_node->maximum_entries_data_size; /* Print all the entries */ for( entry_index = 0; entry_index < index_node->maximum_number_of_entries; entry_index++ ) { if( entry_index == index_node->number_of_entries ) { result = libpff_index_node_check_for_empty_block( index_node_entry_data, index_node_entry_data_size, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if remaining index nodes are empty.", function ); return( -1 ); } else if( result != 0 ) { break; } libcnotify_printf( "\n" ); libcnotify_printf( "%s: remaining node entries\n", function ); } if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint32_little_endian( index_node_entry_data, value_64bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint64_little_endian( index_node_entry_data, value_64bit ); } libcnotify_printf( "%s: entry: %03" PRIu16 " index node identifier\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n", function, entry_index, value_64bit, value_64bit ); /* Process descriptor index node leaf nodes */ if( ( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR ) && ( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) ) { if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_descriptor_entry_32bit_t *) index_node_entry_data )->data_identifier, value_64bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->data_identifier, value_64bit ); } libcnotify_printf( "%s: entry: %03" PRIu16 " data identifier\t\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n", function, entry_index, value_64bit, value_64bit ); if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_descriptor_entry_32bit_t *) index_node_entry_data )->local_descriptors_identifier, value_64bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->local_descriptors_identifier, value_64bit ); } libcnotify_printf( "%s: entry: %03" PRIu16 " local descriptors identifier\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n", function, entry_index, value_64bit, value_64bit ); if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_descriptor_entry_32bit_t *) index_node_entry_data )->parent_identifier, value_32bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->parent_identifier, value_32bit ); } libcnotify_printf( "%s: entry: %03" PRIu16 " parent identifier\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", function, entry_index, value_32bit, value_32bit ); if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_descriptor_entry_64bit_t *) index_node_entry_data )->unknown1, value_32bit ); libcnotify_printf( "%s: entry: %03" PRIu16 " unknown1\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", function, entry_index, value_32bit, value_32bit ); } } /* Process offset and descriptor index node branch nodes and offset index node leaf nodes */ else { if( index_node->level != LIBPFF_INDEX_NODE_LEVEL_LEAF ) { if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_branch_entry_32bit_t *) index_node_entry_data )->back_pointer, value_64bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_branch_entry_64bit_t *) index_node_entry_data )->back_pointer, value_64bit ); } libcnotify_printf( "%s: entry: %03" PRIu16 " back pointer\t\t\t\t: 0x%08" PRIx64 "\n", function, entry_index, value_64bit ); } if( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) { if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_offset_entry_32bit_t *) index_node_entry_data )->file_offset, value_64bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->file_offset, value_64bit ); } } else { if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_branch_entry_32bit_t *) index_node_entry_data )->file_offset, value_64bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint64_little_endian( ( (pff_index_node_branch_entry_64bit_t *) index_node_entry_data )->file_offset, value_64bit ); } } libcnotify_printf( "%s: entry: %03" PRIu16 " file offset\t\t\t\t: 0x%08" PRIx64 " (%" PRIu64 ")\n", function, entry_index, value_64bit, value_64bit ); if( index_node->level == LIBPFF_INDEX_NODE_LEVEL_LEAF ) { if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_offset_entry_32bit_t *) index_node_entry_data )->data_size, value_16bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->data_size, value_16bit ); } libcnotify_printf( "%s: entry: %03" PRIu16 " data size\t\t\t\t: %" PRIu16 "\n", function, entry_index, value_16bit ); if( io_handle->file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_offset_entry_32bit_t *) index_node_entry_data )->reference_count, value_16bit ); } else if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint16_little_endian( ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->reference_count, value_16bit ); } libcnotify_printf( "%s: entry: %03" PRIu16 " reference count\t\t\t: %" PRIu16 "\n", function, entry_index, value_16bit ); if( ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT ) || ( io_handle->file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { byte_stream_copy_to_uint32_little_endian( ( (pff_index_node_offset_entry_64bit_t *) index_node_entry_data )->data_allocation_table_file_offset, value_32bit ); libcnotify_printf( "%s: entry: %03" PRIu16 " data allocation table offset\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", function, entry_index, value_32bit, value_32bit ); } } } index_node_entry_data += index_node->entry_size; index_node_entry_data_size -= index_node->entry_size; } libcnotify_printf( "\n" ); } #endif index_node->entries_data = index_node->data; return( 1 ); on_error: if( index_node->data != NULL ) { memory_free( index_node->data ); index_node->data = NULL; } return( -1 ); }
/* Scans for the event record and adds them to the recovered records array * Returns 1 if successful, 0 if not or -1 on error */ int libevt_io_handle_event_record_scan( libevt_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, off64_t file_offset, size64_t size, libfdata_list_t *recovered_records_list, libcerror_error_t **error ) { libevt_record_values_t *record_values = NULL; uint8_t *scan_block = NULL; static char *function = "libevt_io_handle_event_record_scan"; off64_t record_offset = 0; size_t read_size = 0; size_t scan_block_offset = 0; size_t scan_block_size = 8192; ssize_t read_count = 0; int element_index = 0; 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( file_offset < 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO, "%s: invalid file offset value less than zero.", function ); return( -1 ); } if( size > (off64_t) INT64_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid size value exceeds maximum.", function ); return( -1 ); } scan_block = (uint8_t *) memory_allocate( sizeof( uint8_t ) * scan_block_size ); if( scan_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create scan block.", function ); goto on_error; } while( size > 0 ) { if( libbfio_handle_seek_offset( file_io_handle, file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek scan block offset: %" PRIi64 ".", function, file_offset ); goto on_error; } if( scan_block_size > size ) { read_size = (size_t) size; } else { read_size = scan_block_size; } read_count = libbfio_handle_read_buffer( file_io_handle, scan_block, read_size, error ); if( read_count != (ssize_t) read_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read scan block at offset: %" PRIi64 ".", function, file_offset ); goto on_error; } scan_block_offset = 0; while( scan_block_offset < read_size ) { if( memory_compare( &( scan_block[ scan_block_offset ] ), evt_file_signature, 4 ) != 0 ) { scan_block_offset += 4; continue; } record_offset = file_offset + scan_block_offset - 4; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading recovered record at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, record_offset, record_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, record_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek record offset: %" PRIi64 ".", function, record_offset ); goto on_error; } if( record_values == NULL ) { if( libevt_record_values_initialize( &record_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create record values.", function ); goto on_error; } } read_count = libevt_record_values_read( record_values, file_io_handle, io_handle, &record_offset, 0, error ); if( read_count == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read record at offset: %" PRIi64 ".", function, record_offset ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( ( error != NULL ) && ( *error != NULL ) ) { libcnotify_print_error_backtrace( *error ); } } #endif libcerror_error_free( error ); scan_block_offset += 4; continue; } if( record_values->type == LIBEVT_RECORD_TYPE_EVENT ) { if( libfdata_list_append_element( recovered_records_list, &element_index, 0, file_offset + scan_block_offset - 4, (size64_t) read_count, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append recovered record to records list.", function ); goto on_error; } } if( libevt_record_values_free( &record_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free record values.", function ); goto on_error; } scan_block_offset += read_count - 4; if( ( scan_block_offset + read_count - 4 ) > read_size ) { break; } } file_offset += scan_block_offset; size -= scan_block_offset; } if( record_values != NULL ) { if( libevt_record_values_free( &record_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free record values.", function ); goto on_error; } } memory_free( scan_block ); scan_block = NULL; return( 1 ); on_error: if( record_values != NULL ) { libevt_record_values_free( &record_values, NULL ); } if( scan_block != NULL ) { memory_free( scan_block ); } return( -1 ); }
/* Reads the file header * Returns 1 if successful or -1 on error */ int libqcow_io_handle_read_file_header( libqcow_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, uint32_t *encryption_method, libcerror_error_t **error ) { uint8_t *file_header_data = NULL; static char *function = "libqcow_io_handle_read_file_header"; size_t read_size = 512; ssize_t read_count = 0; uint64_t backing_filename_offset = 0; uint32_t number_of_level1_table_references = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint64_t value_64bit = 0; uint32_t value_32bit = 0; uint16_t value_16bit = 0; #endif 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( io_handle->backing_filename != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid IO handle - backing filename value already set.", function ); return( -1 ); } if( encryption_method == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid encryption method.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading file header at offset: 0 (0x00000000)\n", function ); } #endif if( libbfio_handle_seek_offset( file_io_handle, 0, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek file header offset: 0.", function ); goto on_error; } file_header_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * read_size ); if( file_header_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create file header data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, file_header_data, read_size, error ); if( read_count != (ssize_t) read_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read file header.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: file header data:\n", function ); libcnotify_print_data( file_header_data, sizeof( qcow_file_header_v1_t ), 0 ); } #endif if( memory_compare( ( (qcow_file_header_v1_t *) file_header_data )->signature, qcow_file_signature, 4 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported file signature.", function ); goto on_error; } byte_stream_copy_to_uint32_big_endian( ( (qcow_file_header_v1_t *) file_header_data )->format_version, io_handle->format_version ); byte_stream_copy_to_uint64_big_endian( ( (qcow_file_header_v1_t *) file_header_data )->backing_filename_offset, backing_filename_offset ); byte_stream_copy_to_uint32_big_endian( ( (qcow_file_header_v1_t *) file_header_data )->backing_filename_size, io_handle->backing_filename_size ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { byte_stream_copy_to_uint32_big_endian( ( (qcow_file_header_v1_t *) file_header_data )->signature, value_32bit ); libcnotify_printf( "%s: signature\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: format version\t\t\t: %" PRIu32 "\n", function, io_handle->format_version ); libcnotify_printf( "%s: backing filename offset\t\t: %" PRIu32 "\n", function, backing_filename_offset ); libcnotify_printf( "%s: backing filename size\t\t: %" PRIu32 "\n", function, io_handle->backing_filename_size ); } #endif if( ( io_handle->format_version != 1 ) && ( io_handle->format_version != 2 ) && ( io_handle->format_version != 3 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported format version: %" PRIu32 ".", function, io_handle->format_version ); goto on_error; } if( io_handle->format_version == 1 ) { byte_stream_copy_to_uint64_big_endian( ( (qcow_file_header_v1_t *) file_header_data )->media_size, io_handle->media_size ); io_handle->number_of_cluster_block_bits = (uint32_t) ( (qcow_file_header_v1_t *) file_header_data )->number_of_cluster_block_bits; io_handle->number_of_level2_table_bits = (uint32_t) ( (qcow_file_header_v1_t *) file_header_data )->number_of_level2_table_bits; byte_stream_copy_to_uint32_big_endian( ( (qcow_file_header_v1_t *) file_header_data )->encryption_method, *encryption_method ); byte_stream_copy_to_uint64_big_endian( ( (qcow_file_header_v2_t *) file_header_data )->level1_table_offset, io_handle->level1_table_offset ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { byte_stream_copy_to_uint32_big_endian( ( (qcow_file_header_v1_t *) file_header_data )->modification_time, value_32bit ); libcnotify_printf( "%s: modification time\t\t\t: %" PRIu32 "\n", function, value_32bit ); libcnotify_printf( "%s: media size\t\t\t\t: %" PRIu64 "\n", function, io_handle->media_size ); libcnotify_printf( "%s: number of cluster block bits\t: %" PRIu32 "\n", function, io_handle->number_of_cluster_block_bits ); libcnotify_printf( "%s: number of level 2 table bits\t: %" PRIu32 "\n", function, io_handle->number_of_level2_table_bits ); byte_stream_copy_to_uint16_big_endian( ( (qcow_file_header_v1_t *) file_header_data )->unknown1, value_16bit ); libcnotify_printf( "%s: unknown1\t\t\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "%s: encryption method\t\t\t: %" PRIu32 "\n", function, *encryption_method ); libcnotify_printf( "%s: level 1 table offset\t\t: 0x%08" PRIx64 "\n", function, io_handle->level1_table_offset ); } #endif } else if( ( io_handle->format_version == 2 ) || ( io_handle->format_version == 3 ) ) { byte_stream_copy_to_uint32_big_endian( ( (qcow_file_header_v2_t *) file_header_data )->number_of_cluster_block_bits, io_handle->number_of_cluster_block_bits ); byte_stream_copy_to_uint32_big_endian( ( (qcow_file_header_v2_t *) file_header_data )->number_of_level1_table_references, number_of_level1_table_references ); byte_stream_copy_to_uint64_big_endian( ( (qcow_file_header_v2_t *) file_header_data )->level1_table_offset, io_handle->level1_table_offset ); byte_stream_copy_to_uint64_big_endian( ( (qcow_file_header_v2_t *) file_header_data )->media_size, io_handle->media_size ); byte_stream_copy_to_uint32_big_endian( ( (qcow_file_header_v2_t *) file_header_data )->encryption_method, *encryption_method ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: number of cluster block bits\t: %" PRIu32 "\n", function, io_handle->number_of_cluster_block_bits ); libcnotify_printf( "%s: media size\t\t\t\t: %" PRIu64 "\n", function, io_handle->media_size ); libcnotify_printf( "%s: encryption method\t\t\t: %" PRIu32 "\n", function, *encryption_method ); libcnotify_printf( "%s: number of level 1 table references\t: %" PRIu32 "\n", function, number_of_level1_table_references ); libcnotify_printf( "%s: level 1 table offset\t\t: 0x%08" PRIx64 "\n", function, io_handle->level1_table_offset ); byte_stream_copy_to_uint64_big_endian( ( (qcow_file_header_v2_t *) file_header_data )->reference_count_table_offset, value_64bit ); libcnotify_printf( "%s: reference count table offset\t: 0x%08" PRIx64 "\n", function, value_64bit ); byte_stream_copy_to_uint32_big_endian( ( (qcow_file_header_v2_t *) file_header_data )->reference_count_table_clusters, value_32bit ); libcnotify_printf( "%s: reference count table clusters\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_big_endian( ( (qcow_file_header_v2_t *) file_header_data )->number_of_snapshots, value_32bit ); libcnotify_printf( "%s: number of snapshots\t\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint64_big_endian( ( (qcow_file_header_v2_t *) file_header_data )->snapshots_offset, value_64bit ); libcnotify_printf( "%s: snapshots offset\t\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); } #endif } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n" ); } #endif memory_free( file_header_data ); file_header_data = NULL; if( io_handle->format_version == 1 ) { io_handle->offset_bit_mask = 0x7fffffffffffffffULL; io_handle->compression_flag_bit_mask = (uint64_t) 1 << 63; io_handle->compression_bit_shift = 63 - io_handle->number_of_cluster_block_bits; } else if( ( io_handle->format_version == 2 ) || ( io_handle->format_version == 3 ) ) { if( io_handle->number_of_cluster_block_bits <= 8 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid number of cluster block bits value out of bounds.", function ); goto on_error; } io_handle->number_of_level2_table_bits = io_handle->number_of_cluster_block_bits - 3; io_handle->offset_bit_mask = 0x3fffffffffffffffULL; io_handle->compression_flag_bit_mask = (uint64_t) 1 << 62; io_handle->compression_bit_shift = 62 - ( io_handle->number_of_cluster_block_bits - 8 ); } io_handle->level1_index_bit_shift = io_handle->number_of_cluster_block_bits + io_handle->number_of_level2_table_bits; io_handle->level2_index_bit_mask = ~( (uint64_t) -1 << io_handle->number_of_level2_table_bits ); io_handle->cluster_block_bit_mask = ~( (uint64_t) -1 << io_handle->number_of_cluster_block_bits ); io_handle->compression_bit_mask = ~( (uint64_t) -1 << io_handle->compression_bit_shift ); io_handle->level2_table_size = (size_t) 1 << io_handle->number_of_level2_table_bits; io_handle->cluster_block_size = (size_t) 1 << io_handle->number_of_cluster_block_bits; if( io_handle->format_version == 1 ) { io_handle->level1_table_size = (uint32_t) ( io_handle->cluster_block_size * io_handle->level2_table_size ); if( ( io_handle->media_size % io_handle->level1_table_size ) != 0 ) { io_handle->level1_table_size = (uint32_t) ( ( io_handle->media_size / io_handle->level1_table_size ) + 1 ); } else { io_handle->level1_table_size = (uint32_t) ( io_handle->media_size / io_handle->level1_table_size ); } } else if( ( io_handle->format_version == 2 ) || ( io_handle->format_version == 3 ) ) { io_handle->level1_table_size = number_of_level1_table_references; } io_handle->level1_table_size *= 8; io_handle->level2_table_size *= 8; #if UINT32_MAX > SSIZE_MAX if( io_handle->level1_table_size > (uint32_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid level 1 table size value exceeds maximum.", function ); goto on_error; } #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: level 1 table size\t\t\t: %" PRIzd "\n", function, io_handle->level1_table_size ); libcnotify_printf( "%s: level 2 table size\t\t\t: %" PRIzd "\n", function, io_handle->level2_table_size ); libcnotify_printf( "%s: cluster block size\t\t\t: %" PRIzd "\n", function, io_handle->cluster_block_size ); } #endif if( ( backing_filename_offset > 0 ) && ( io_handle->backing_filename_size > 0 ) ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading backing filename at offset: %" PRIu64 " (0x%08" PRIx64 ")\n", function, backing_filename_offset, backing_filename_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, backing_filename_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek file header offset: %" PRIu64 ".", function, backing_filename_offset ); goto on_error; } io_handle->backing_filename = (uint8_t *) memory_allocate( sizeof( uint8_t ) * io_handle->backing_filename_size ); if( io_handle->backing_filename == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create backing filename.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, io_handle->backing_filename, io_handle->backing_filename_size, error ); if( read_count != (ssize_t) io_handle->backing_filename_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read file header.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: backing filename data:\n", function ); libcnotify_print_data( io_handle->backing_filename, (size_t) io_handle->backing_filename_size, 0 ); } #endif } return( 1 ); on_error: if( io_handle->backing_filename != NULL ) { memory_free( io_handle->backing_filename ); io_handle->backing_filename = NULL; io_handle->backing_filename_size = 0; } if( file_header_data != NULL ) { memory_free( file_header_data ); } return( -1 ); }
/* Reads the file (or database) header * Returns 1 if successful or -1 on error */ int libesedb_io_handle_read_file_header( libesedb_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, off64_t file_offset, libcerror_error_t **error ) { uint8_t *file_header_data = NULL; static char *function = "libesedb_io_handle_read_file_header"; size_t read_size = 2048; ssize_t read_count = 0; uint32_t calculated_xor32_checksum = 0; uint32_t creation_format_revision = 0; uint32_t creation_format_version = 0; uint32_t format_revision = 0; uint32_t format_version = 0; uint32_t page_size = 0; uint32_t stored_xor32_checksum = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint32_t value_32bit = 0; #endif 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 defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading file header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, file_offset, file_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek file header offset: %" PRIi64 ".", function, file_offset ); goto on_error; } file_header_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * read_size ); if( file_header_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create file header data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, file_header_data, read_size, error ); if( read_count != (ssize_t) read_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read file header.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: file header data:\n", function ); libcnotify_print_data( file_header_data, sizeof( esedb_file_header_t ), LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif if( memory_compare( ( (esedb_file_header_t *) file_header_data )->signature, esedb_file_signature, 4 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported file signature.", function ); goto on_error; } if( libesedb_checksum_calculate_little_endian_xor32( &calculated_xor32_checksum, &( file_header_data[ 4 ] ), read_size - 4, 0x89abcdef, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GENERIC, "%s: unable to calculate XOR-32 checksum.", function ); goto on_error; } byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->checksum, stored_xor32_checksum ); if( stored_xor32_checksum != calculated_xor32_checksum ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_INPUT, LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH, "%s: mismatch in file header checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).", function, stored_xor32_checksum, calculated_xor32_checksum ); goto on_error; } byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->format_version, format_version ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->file_type, io_handle->file_type ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->format_revision, format_revision ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->page_size, page_size ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->creation_format_version, creation_format_version ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->creation_format_revision, creation_format_revision ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n", function, stored_xor32_checksum ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->signature, value_32bit ); libcnotify_printf( "%s: signature\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: format version\t\t\t: 0x%08" PRIx32 "\n", function, format_version ); libcnotify_printf( "%s: file type\t\t\t\t: %" PRIu32 " (", function, io_handle->file_type ); libesedb_debug_print_file_type( io_handle->file_type ); libcnotify_printf( ")\n" ); libcnotify_printf( "%s: database time:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->database_time, 8, 0 ); libcnotify_printf( "%s: database signature:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->database_signature, 28, 0 ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->database_state, value_32bit ); libcnotify_printf( "%s: database state\t\t\t: %" PRIu32 " ", function, value_32bit ); libesedb_debug_print_database_state( value_32bit ); libcnotify_printf( "\n" ); libcnotify_printf( "%s: consistent position:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->consistent_postition, 8, 0 ); libesedb_debug_print_log_time( ( (esedb_file_header_t *) file_header_data )->consistent_time, 8, "consistent time", "\t\t\t\t", NULL ); libesedb_debug_print_log_time( ( (esedb_file_header_t *) file_header_data )->attach_time, 8, "attach time", "\t\t\t\t", NULL ); libcnotify_printf( "%s: attach position:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->attach_postition, 8, 0 ); libesedb_debug_print_log_time( ( (esedb_file_header_t *) file_header_data )->detach_time, 8, "detach time", "\t\t\t\t", NULL ); libcnotify_printf( "%s: detach position:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->detach_postition, 8, 0 ); libcnotify_printf( "%s: log signature:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->log_signature, 28, 0 ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->unknown1, value_32bit ); libcnotify_printf( "%s: unknown1\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", function, value_32bit, value_32bit ); libcnotify_printf( "%s: previous full backup:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->previous_full_backup, 24, 0 ); libcnotify_printf( "%s: previous incremental backup:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->previous_incremental_backup, 24, 0 ); libcnotify_printf( "%s: current full backup:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->current_full_backup, 24, 0 ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->shadowing_disabled, value_32bit ); libcnotify_printf( "%s: shadowing disabled\t\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->last_object_identifier, value_32bit ); libcnotify_printf( "%s: last object identifier\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->index_update_major_version, value_32bit ); libcnotify_printf( "%s: index update major version\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->index_update_minor_version, value_32bit ); libcnotify_printf( "%s: index update minor version\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->index_update_build_number, value_32bit ); libcnotify_printf( "%s: index update build number\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->index_update_service_pack_number, value_32bit ); libcnotify_printf( "%s: index update service pack number\t: %" PRIu32 "\n", function, value_32bit ); libcnotify_printf( "%s: format revision\t\t\t: 0x%08" PRIx32 "\n", function, format_revision ); libcnotify_printf( "%s: page size\t\t\t\t: %" PRIu32 "\n", function, page_size ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->repair_count, value_32bit ); libcnotify_printf( "%s: repair count\t\t\t: %" PRIu32 "\n", function, value_32bit ); libesedb_debug_print_log_time( ( (esedb_file_header_t *) file_header_data )->repair_time, 8, "repair time", "\t\t\t\t", NULL ); libcnotify_printf( "%s: unknown2:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->unknown2, 28, 0 ); libcnotify_printf( "%s: scrub database time:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->scrub_database_time, 8, 0 ); libesedb_debug_print_log_time( ( (esedb_file_header_t *) file_header_data )->scrub_time, 8, "scrub time", "\t\t\t\t", NULL ); libcnotify_printf( "%s: required log:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->required_log, 8, 0 ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->upgrade_exchange5_format, value_32bit ); libcnotify_printf( "%s: upgrade Exchange 5.5 format\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->upgrade_free_pages, value_32bit ); libcnotify_printf( "%s: upgrade free pages\t\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->upgrade_space_map_pages, value_32bit ); libcnotify_printf( "%s: upgrade space map pages\t\t: %" PRIu32 "\n", function, value_32bit ); libcnotify_printf( "%s: current shadow volume backup:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->current_shadow_volume_backup, 24, 0 ); libcnotify_printf( "%s: creation format version\t\t: 0x%08" PRIx32 "\n", function, creation_format_version ); libcnotify_printf( "%s: creation format revision\t\t: 0x%08" PRIx32 "\n", function, creation_format_revision ); libcnotify_printf( "%s: unknown3:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->unknown3, 16, 0 ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->old_repair_count, value_32bit ); libcnotify_printf( "%s: old repair count\t\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->ecc_fix_success_count, value_32bit ); libcnotify_printf( "%s: ECC fix success count\t\t: %" PRIu32 "\n", function, value_32bit ); libesedb_debug_print_log_time( ( (esedb_file_header_t *) file_header_data )->ecc_fix_success_time, 8, "ECC fix success time", "\t\t\t", NULL ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->old_ecc_fix_success_count, value_32bit ); libcnotify_printf( "%s: old ECC fix success count\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->ecc_fix_error_count, value_32bit ); libcnotify_printf( "%s: ECC fix error count\t\t: %" PRIu32 "\n", function, value_32bit ); libesedb_debug_print_log_time( ( (esedb_file_header_t *) file_header_data )->ecc_fix_error_time, 8, "ECC fix error time", "\t\t\t", NULL ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->old_ecc_fix_error_count, value_32bit ); libcnotify_printf( "%s: old ECC fix error count\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->bad_checksum_error_count, value_32bit ); libcnotify_printf( "%s: bad checksum error count\t\t: %" PRIu32 "\n", function, value_32bit ); libesedb_debug_print_log_time( ( (esedb_file_header_t *) file_header_data )->bad_checksum_error_time, 8, "bad checksum error time", "\t\t\t", NULL ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->old_bad_checksum_error_count, value_32bit ); libcnotify_printf( "%s: old bad checksum error count\t: %" PRIu32 "\n", function, value_32bit ); libcnotify_printf( "%s: committed log:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->committed_log, 4, 0 ); libcnotify_printf( "%s: previous shadow volume backup:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->previous_shadow_volume_backup, 24, 0 ); libcnotify_printf( "%s: previous differential backup:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->previous_differential_backup, 24, 0 ); libcnotify_printf( "%s: unknown4:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->unknown4, 40, 0 ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->nls_major_version, value_32bit ); libcnotify_printf( "%s: NLS major version\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->nls_minor_version, value_32bit ); libcnotify_printf( "%s: NLS minor version\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: unknown5:\n", function ); libcnotify_print_data( ( (esedb_file_header_t *) file_header_data )->unknown5, 148, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); byte_stream_copy_to_uint32_little_endian( ( (esedb_file_header_t *) file_header_data )->unknown_flags, value_32bit ); libcnotify_printf( "%s: unknown flags\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", function, value_32bit, value_32bit ); libcnotify_printf( "\n" ); } #endif memory_free( file_header_data ); file_header_data = NULL; /* TODO add more values to internal structures */ if( file_offset == 0 ) { io_handle->format_version = format_version; io_handle->format_revision = format_revision; io_handle->page_size = page_size; io_handle->creation_format_version = creation_format_version; io_handle->creation_format_revision = creation_format_revision; } else { if( io_handle->format_version == 0 ) { io_handle->format_version = format_version; } else if( io_handle->format_version != format_version ) { #if defined( HAVE_VERBOSE_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: mismatch in format version: 0x%" PRIx32 " and backup: 0x%" PRIx32 "\n", function, io_handle->format_version, io_handle->format_version ); } #endif } if( io_handle->format_revision == 0 ) { io_handle->format_revision = format_revision; } else if( io_handle->format_revision != format_revision ) { #if defined( HAVE_VERBOSE_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: mismatch in format revision: 0x%" PRIx32 " and backup: 0x%" PRIx32 "\n", function, io_handle->format_revision, io_handle->format_revision ); } #endif } if( io_handle->page_size == 0 ) { io_handle->page_size = page_size; } else if( io_handle->page_size != page_size ) { #if defined( HAVE_VERBOSE_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: mismatch in page size: 0x%04" PRIx32 " and backup: 0x%04" PRIx32 "\n", function, io_handle->page_size, page_size ); } #endif /* The offset of the backup (database) file header * is a good indication of the actual page size */ io_handle->page_size = (uint32_t) file_offset; } } return( 1 ); on_error: if( file_header_data != NULL ) { memory_free( file_header_data ); } return( -1 ); }
/* Reads the version (resource) values * Returns 1 if successful or -1 on error */ int libwrc_version_values_read( libwrc_language_entry_t *language_entry, libwrc_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libwrc_data_descriptor_t *data_descriptor, libcerror_error_t **error ) { libwrc_version_values_t *version_values = NULL; libfvalue_value_t *value_identifier = NULL; uint8_t *resource_data = NULL; uint8_t *version_resource_data = NULL; static char *function = "libwrc_version_values_read"; off64_t file_offset = 0; size_t alignment_padding_size = 0; size_t resource_data_offset = 0; size_t resource_data_size = 0; ssize_t read_count = 0; uint32_t value_32bit = 0; uint16_t value_data_size = 0; uint16_t value_data_type = 0; uint16_t version_resource_data_size = 0; int value_index = 0; if( language_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid language entry.", 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_descriptor == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data descriptor.", function ); return( -1 ); } if( libwrc_version_values_initialize( &version_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create version values.", function ); goto on_error; } file_offset = data_descriptor->virtual_address - io_handle->virtual_address; if( libbfio_handle_seek_offset( file_io_handle, file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek resource data offset: %" PRIi64 ".", function, file_offset ); goto on_error; } resource_data_size = (size_t) data_descriptor->size; resource_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * resource_data_size ); if( resource_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create resource data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, resource_data, resource_data_size, error ); if( read_count != (ssize_t) resource_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read resource data.", function ); goto on_error; } version_resource_data = resource_data; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: resource data:\n", function ); libcnotify_print_data( version_resource_data, resource_data_size, 0 ); } #endif byte_stream_copy_to_uint16_little_endian( ( (wrc_version_value_header_t *) version_resource_data )->size, version_resource_data_size ); byte_stream_copy_to_uint16_little_endian( ( (wrc_version_value_header_t *) version_resource_data )->value_data_size, value_data_size ); byte_stream_copy_to_uint16_little_endian( ( (wrc_version_value_header_t *) version_resource_data )->value_data_type, value_data_type ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: size\t\t\t\t\t: %" PRIu16 "\n", function, version_resource_data_size ); libcnotify_printf( "%s: value data size\t\t\t\t: %" PRIu16 "\n", function, value_data_size ); libcnotify_printf( "%s: value data type\t\t\t\t: %" PRIu16 "\n", function, value_data_type ); libcnotify_printf( "\n" ); } #endif resource_data_offset += sizeof( wrc_version_value_header_t ); if( libfvalue_value_type_initialize( &value_identifier, LIBFVALUE_VALUE_TYPE_STRING_UTF16, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create value identifier value.", function ); goto on_error; } read_count = libfvalue_value_type_set_data_string( value_identifier, &( version_resource_data[ resource_data_offset ] ), resource_data_size, LIBFVALUE_CODEPAGE_UTF16_LITTLE_ENDIAN, LIBFVALUE_VALUE_DATA_FLAG_MANAGED, error ); if( read_count == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set data of value identifier value.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: value identifier\t\t\t\t: ", function ); if( libfvalue_value_print( value_identifier, 0, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print value identifier value.", function ); goto on_error; } libcnotify_printf( "\n" ); } #endif if( ( read_count != 32 ) || ( memory_compare( &( version_resource_data[ resource_data_offset ] ), libwrc_version_information_value_identifier, 32 ) != 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported version resource value signature.", function ); goto on_error; } if( libfvalue_value_free( &value_identifier, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free value identifier value.", function ); goto on_error; } resource_data_offset += read_count; if( ( resource_data_offset % 4 ) != 0 ) { alignment_padding_size = 4 - ( resource_data_offset % 4 ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: alignment padding:\n", function ); libcnotify_print_data( &( version_resource_data[ resource_data_offset ] ), alignment_padding_size, 0 ); } #endif resource_data_offset += alignment_padding_size; } /* TODO refactor to separate function? */ if( value_data_size > 0 ) { if( value_data_size > resource_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: value data size value out of bounds.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: value data:\n", function ); libcnotify_print_data( &( version_resource_data[ resource_data_offset ] ), value_data_size, 0 ); } #endif byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 8 ] ), version_values->file_version ); byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 12 ] ), value_32bit ); version_values->file_version <<= 32; version_values->file_version |= value_32bit; byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 16 ] ), version_values->product_version ); byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 20 ] ), value_32bit ); version_values->product_version <<= 32; version_values->product_version |= value_32bit; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset ] ), value_32bit ); libcnotify_printf( "%s: signature\t\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 4 ] ), value_32bit ); libcnotify_printf( "%s: version\t\t\t\t\t: %" PRIu32 ".%" PRIu32 "\n", function, value_32bit >> 16, value_32bit & 0x0000ffffUL ); byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 8 ] ), value_32bit ); libcnotify_printf( "%s: file version upper\t\t\t\t: %" PRIu32 ".%" PRIu32 "\n", function, value_32bit >> 16, value_32bit & 0x0000ffffUL ); byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 12 ] ), value_32bit ); libcnotify_printf( "%s: file version lower\t\t\t\t: %" PRIu32 ".%" PRIu32 "\n", function, value_32bit >> 16, value_32bit & 0x0000ffffUL ); byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 16 ] ), value_32bit ); libcnotify_printf( "%s: product version upper\t\t\t: %" PRIu32 ".%" PRIu32 "\n", function, value_32bit >> 16, value_32bit & 0x0000ffffUL ); byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 20 ] ), value_32bit ); libcnotify_printf( "%s: product version lower\t\t\t: %" PRIu32 ".%" PRIu32 "\n", function, value_32bit >> 16, value_32bit & 0x0000ffffUL ); byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 24 ] ), value_32bit ); libcnotify_printf( "%s: file flags bitmask\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 28 ] ), value_32bit ); libcnotify_printf( "%s: file flags\t\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 32 ] ), value_32bit ); libcnotify_printf( "%s: file operating system\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 36 ] ), value_32bit ); libcnotify_printf( "%s: file type\t\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 40 ] ), value_32bit ); libcnotify_printf( "%s: file sub type\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 44 ] ), value_32bit ); libcnotify_printf( "%s: file time upper\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( &( version_resource_data[ resource_data_offset + 48 ] ), value_32bit ); libcnotify_printf( "%s: file time lower\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "\n" ); } #endif resource_data_offset += value_data_size; }
/* Reads the memory image information * Returns 1 if successful or -1 on error */ int libhibr_io_handle_read_memory_image_information( libhibr_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { uint8_t *page_data = NULL; static char *function = "libhibr_io_handle_read_memory_image_information"; ssize_t read_count = 0; uint64_t page_size = 0; uint32_t memory_image_information_data_size = 0; #if defined( HAVE_DEBUG_OUTPUT ) libcstring_system_character_t filetime_string[ 32 ]; libfdatetime_filetime_t *filetime = NULL; uint64_t value_64bit = 0; uint32_t value_32bit = 0; uint8_t value_8bit = 0; int result = 0; #endif 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 defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading memory image information at offset: 0.\n", function ); } #endif if( libbfio_handle_seek_offset( file_io_handle, 0, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek memory image information offset: 0.", function ); goto on_error; } page_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * io_handle->page_size ); if( page_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create memory image information data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, page_data, io_handle->page_size, error ); if( read_count != (ssize_t) io_handle->page_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read memory image information.", function ); goto on_error; } /* TODO do empty page test */ byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_t *) page_data )->size, memory_image_information_data_size ); if( memory_image_information_data_size > 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: memory image information data:\n", function ); libcnotify_print_data( page_data, (size_t) memory_image_information_data_size, 0 ); } #endif /* TODO if( memory_compare( ( (hibr_memory_image_information_t *) page_data )->signature, hibr_file_signature, 8 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported file signature.", function ); goto on_error; } */ if( memory_image_information_data_size == sizeof( hibr_memory_image_information_winxp_32bit_t ) ) { io_handle->file_type = LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT; } else if( memory_image_information_data_size == sizeof( hibr_memory_image_information_winxp_64bit_t ) ) { io_handle->file_type = LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT; } else if( memory_image_information_data_size == sizeof( hibr_memory_image_information_win7_32bit_t ) ) { io_handle->file_type = LIBHIBR_FILE_TYPE_WINDOWS_7_32BIT; } else if( memory_image_information_data_size == sizeof( hibr_memory_image_information_win7_64bit_t ) ) { io_handle->file_type = LIBHIBR_FILE_TYPE_WINDOWS_7_64BIT; } if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->page_size, page_size ); } else if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_64bit_t *) page_data )->page_size, page_size ); } else if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_7_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_win7_32bit_t *) page_data )->page_size, page_size ); } else if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_7_64BIT ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_win7_64bit_t *) page_data )->page_size, page_size ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: signature\t\t: %c%c%c%c\n", function, ( (hibr_memory_image_information_t *) page_data )->signature[ 0 ], ( (hibr_memory_image_information_t *) page_data )->signature[ 1 ], ( (hibr_memory_image_information_t *) page_data )->signature[ 2 ], ( (hibr_memory_image_information_t *) page_data )->signature[ 3 ] ); if( ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) || ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->version, value_32bit ); libcnotify_printf( "%s: version\t\t: %" PRIu32 "\n", function, value_32bit ); } else if( ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_7_32BIT ) || ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_7_64BIT ) ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_win7_32bit_t *) page_data )->image_type, value_32bit ); libcnotify_printf( "%s: image type\t\t: %" PRIu32 "\n", function, value_32bit ); } byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_t *) page_data )->checksum, value_32bit ); libcnotify_printf( "%s: checksum\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: size\t\t\t: %" PRIu32 "\n", function, memory_image_information_data_size ); if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->page_number, value_64bit ); } else if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) { byte_stream_copy_to_uint64_little_endian( ( (hibr_memory_image_information_winxp_64bit_t *) page_data )->page_number, value_64bit ); } else if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_7_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_win7_32bit_t *) page_data )->page_number, value_64bit ); } else if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_7_64BIT ) { byte_stream_copy_to_uint64_little_endian( ( (hibr_memory_image_information_win7_64bit_t *) page_data )->page_number, value_64bit ); } libcnotify_printf( "%s: page number\t\t: %" PRIu64 "\n", function, value_64bit ); libcnotify_printf( "%s: page size\t\t: %" PRIu64 "\n", function, page_size ); if( ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) || ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) ) { if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->image_type, value_32bit ); } else { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_64bit_t *) page_data )->image_type, value_32bit ); } libcnotify_printf( "%s: image type\t\t: %" PRIu32 "\n", function, value_32bit ); } if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->unknown1, value_32bit ); libcnotify_printf( "%s: unknown1\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); } if( ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) || ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) ) { byte_stream_copy_to_uint64_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->system_time, value_64bit ); } else if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_7_32BIT ) { byte_stream_copy_to_uint64_little_endian( ( (hibr_memory_image_information_win7_32bit_t *) page_data )->system_time, value_64bit ); } else if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_7_64BIT ) { byte_stream_copy_to_uint64_little_endian( ( (hibr_memory_image_information_win7_64bit_t *) page_data )->system_time, value_64bit ); } if( libfdatetime_filetime_initialize( &filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create filetime.", function ); goto on_error; } if( libfdatetime_filetime_copy_from_64bit( filetime, value_64bit, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy byte stream to filetime.", function ); goto on_error; } #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) result = libfdatetime_filetime_copy_to_utf16_string( filetime, (uint16_t *) filetime_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ); #else result = libfdatetime_filetime_copy_to_utf8_string( filetime, (uint8_t *) filetime_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy filetime to string.", function ); goto on_error; } libcnotify_printf( "%s: system time\t\t: %" PRIs_LIBCSTRING_SYSTEM " UTC\n", function, filetime_string ); if( libfdatetime_filetime_free( &filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free filetime.", function ); goto on_error; } if( ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) || ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) ) { byte_stream_copy_to_uint64_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->interrupt_time, value_64bit ); } libcnotify_printf( "%s: interrupt time\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); if( ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) || ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->feature_flags, value_32bit ); } libcnotify_printf( "%s: feature flags\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); if( ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) || ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) ) { value_8bit = ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->hibernation_flags; } libcnotify_printf( "%s: hibernation flags\t: 0x%02" PRIx8 "\n", function, value_8bit ); if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) { libcnotify_printf( "%s: unknown2:\n", function ); libcnotify_print_data( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->unknown2, 3, 0 ); } else if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) { libcnotify_printf( "%s: unknown1:\n", function ); libcnotify_print_data( ( (hibr_memory_image_information_winxp_64bit_t *) page_data )->unknown1, 3, 0 ); byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_64bit_t *) page_data )->unknown2, value_32bit ); libcnotify_printf( "%s: unknown2\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); } if( ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) || ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->unknown3, value_32bit ); } libcnotify_printf( "%s: unknown3\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); if( ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) || ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->unknown4, value_32bit ); } libcnotify_printf( "%s: unknown4\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); if( ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) || ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) ) { byte_stream_copy_to_uint64_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->unknown5, value_64bit ); } libcnotify_printf( "%s: unknown5\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); if( ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) || ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->number_of_free_pages, value_32bit ); } libcnotify_printf( "%s: number of free pages\t: %" PRIu32 "\n", function, value_32bit ); if( ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) || ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->unknown6, value_32bit ); } libcnotify_printf( "%s: unknown6\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); if( ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) || ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->unknown7, value_32bit ); } libcnotify_printf( "%s: unknown7\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_64bit_t *) page_data )->unknown8, value_32bit ); libcnotify_printf( "%s: unknown8\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); } if( ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) || ( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->number_of_pages, value_32bit ); } libcnotify_printf( "%s: number of pages\t: %" PRIu32 "\n", function, value_32bit ); if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_32BIT ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->unknown8, value_32bit ); libcnotify_printf( "%s: unknown8\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->unknown9, value_32bit ); libcnotify_printf( "%s: unknown9\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: unknown10:\n", function ); libcnotify_print_data( ( (hibr_memory_image_information_winxp_32bit_t *) page_data )->unknown10, 72, 0 ); } else if( io_handle->file_type == LIBHIBR_FILE_TYPE_WINDOWS_XP_64BIT ) { byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_64bit_t *) page_data )->unknown8, value_32bit ); libcnotify_printf( "%s: unknown8\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (hibr_memory_image_information_winxp_64bit_t *) page_data )->unknown9, value_32bit ); libcnotify_printf( "%s: unknown9\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: unknown10:\n", function ); libcnotify_print_data( ( (hibr_memory_image_information_winxp_64bit_t *) page_data )->unknown10, 72, 0 ); } else { libcnotify_printf( "\n" ); } } #endif } #if defined( HAVE_DEBUG_OUTPUT ) else if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: page data:\n", function ); libcnotify_print_data( page_data, io_handle->page_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif /* TODO print trailing data */ /* TODO page size sanity check */ io_handle->page_size = (size_t) page_size; /* TODO memory blocks page number sanity check */ memory_free( page_data ); page_data = NULL; return( 1 ); on_error: #if defined( HAVE_DEBUG_OUTPUT ) if( filetime != NULL ) { libfdatetime_filetime_free( &filetime, NULL ); } #endif if( page_data != NULL ) { memory_free( page_data ); } return( -1 ); }
/* Reads an free map * Returns 1 if successful or -1 on error */ int libpff_free_map_read( libcdata_range_list_t *unallocated_block_list, libbfio_handle_t *file_io_handle, off64_t free_map_offset, uint8_t file_type, libcerror_error_t **error ) { uint8_t *free_map_data = NULL; uint8_t *table_data = NULL; static char *function = "libpff_free_map_read"; off64_t back_pointer_offset = 0; off64_t unallocated_offset = 0; size_t read_size = 0; size_t unallocated_size = 0; size_t allocation_block_size = 0; ssize_t read_count = 0; uint32_t stored_checksum = 0; uint32_t calculated_checksum = 0; uint16_t table_iterator = 0; uint8_t bit_iterator = 0; uint8_t free_map_entry = 0; uint8_t free_map_type = 0; uint8_t free_map_type_copy = 0; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint16_t value_16bit = 0; #endif if( unallocated_block_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid unallocated block list.", function ); return( -1 ); } if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } if( ( file_type != LIBPFF_FILE_TYPE_32BIT ) && ( file_type != LIBPFF_FILE_TYPE_64BIT ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported file type.", function ); return( -1 ); } if( libbfio_handle_seek_offset( file_io_handle, free_map_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek free map offset: %" PRIi64 ".", function, free_map_offset ); goto on_error; } if( file_type == LIBPFF_FILE_TYPE_32BIT ) { read_size = sizeof( pff_free_map_32bit_t ); } else if( file_type == LIBPFF_FILE_TYPE_64BIT ) { read_size = sizeof( pff_free_map_64bit_t ); } free_map_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * read_size ); if( free_map_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create alloction table data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, free_map_data, read_size, error ); if( read_count != (ssize_t) read_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read free map.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: free map:\n", function ); libcnotify_print_data( free_map_data, read_size, 0 ); } #endif if( file_type == LIBPFF_FILE_TYPE_32BIT ) { table_data = ( (pff_free_map_32bit_t *) free_map_data )->data; free_map_type = ( (pff_free_map_32bit_t *) free_map_data )->type; free_map_type_copy = ( (pff_free_map_32bit_t *) free_map_data )->type_copy; byte_stream_copy_to_uint32_little_endian( ( (pff_free_map_32bit_t *) free_map_data )->back_pointer, back_pointer_offset ); byte_stream_copy_to_uint32_little_endian( ( (pff_free_map_32bit_t *) free_map_data )->checksum, stored_checksum ); } else if( file_type == LIBPFF_FILE_TYPE_64BIT ) { table_data = ( (pff_free_map_64bit_t *) free_map_data )->data; free_map_type = ( (pff_free_map_64bit_t *) free_map_data )->type; free_map_type_copy = ( (pff_free_map_64bit_t *) free_map_data )->type_copy; byte_stream_copy_to_uint32_little_endian( ( (pff_free_map_64bit_t *) free_map_data )->checksum, stored_checksum ); byte_stream_copy_to_uint64_little_endian( ( (pff_free_map_64bit_t *) free_map_data )->back_pointer, back_pointer_offset ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: type\t\t: 0x%02" PRIx8 "\n", function, free_map_type ); libcnotify_printf( "%s: type copy\t: 0x%02" PRIx8 "\n", function, free_map_type_copy ); if( file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint16_little_endian( ( (pff_free_map_32bit_t *) free_map_data )->signature, value_16bit ); libcnotify_printf( "%s: signature\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "%s: back pointer\t: %" PRIu64 "\n", function, back_pointer_offset ); libcnotify_printf( "%s: checksum\t: 0x%" PRIx32 "\n", function, stored_checksum ); } else if( file_type == LIBPFF_FILE_TYPE_64BIT ) { byte_stream_copy_to_uint16_little_endian( ( (pff_free_map_64bit_t *) free_map_data )->signature, value_16bit ); libcnotify_printf( "%s: signature\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "%s: checksum\t\t: 0x%" PRIx32 "\n", function, stored_checksum ); libcnotify_printf( "%s: back pointer\t: %" PRIu64 "\n", function, back_pointer_offset ); } libcnotify_printf( "\n" ); } #endif if( libfmapi_checksum_calculate_weak_crc32( &calculated_checksum, table_data, 496, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to calculate weak CRC-32.", function ); goto on_error; } if( stored_checksum != calculated_checksum ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_INPUT, LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH, "%s: mismatch in checksum ( %" PRIu32 " != %" PRIu32 " ).", function, stored_checksum, calculated_checksum ); /* TODO implement error tollerance */ goto on_error; } if( free_map_type != free_map_type_copy ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_INPUT, LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH, "%s: mismatch in allocation table type ( 0x%02" PRIx8 " != 0x%02" PRIx8 " ).", function, free_map_type, free_map_type_copy ); /* TODO implement error tollerance */ goto on_error; } if( ( free_map_type != LIBPFF_FREE_MAP_TYPE_DATA ) && ( free_map_type != LIBPFF_FREE_MAP_TYPE_PAGE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported allocation table type: 0x%08" PRIx32 "", function, free_map_type ); /* TODO implement error tollerance */ goto on_error; } /* TODO */ if( free_map_type == LIBPFF_FREE_MAP_TYPE_PAGE ) { allocation_block_size = 512; back_pointer_offset -= 0x200; } else if( free_map_type == LIBPFF_FREE_MAP_TYPE_DATA ) { allocation_block_size = 64; } for( table_iterator = 0; table_iterator < 496; table_iterator++ ) { free_map_entry = table_data[ table_iterator ]; for( bit_iterator = 0; bit_iterator < 8; bit_iterator++ ) { if( ( free_map_entry & 0x80 ) == 0 ) { if( unallocated_size == 0 ) { unallocated_offset = back_pointer_offset; } unallocated_size += allocation_block_size; } else if( unallocated_size > 0 ) { result = libcdata_range_list_insert_range( unallocated_block_list, unallocated_offset, unallocated_size, NULL, NULL, NULL, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append unallocated block to list.", function ); goto on_error; } unallocated_size = 0; } free_map_entry <<= 1; back_pointer_offset += allocation_block_size; } } if( unallocated_size > 0 ) { result = libcdata_range_list_insert_range( unallocated_block_list, unallocated_offset, unallocated_size, NULL, NULL, NULL, error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append unallocated block to list.", function ); goto on_error; } unallocated_size = 0; } memory_free( free_map_data ); return( 1 ); on_error: if( free_map_data != NULL ) { memory_free( free_map_data ); } return( -1 ); }
/* Reads the store block * Returns 1 if successful or -1 on error */ int libvshadow_store_block_read( libvshadow_store_block_t *store_block, libbfio_handle_t *file_io_handle, off64_t file_offset, libcerror_error_t **error ) { static char *function = "libvshadow_store_block_read"; ssize_t read_count = 0; #if defined( HAVE_DEBUG_OUTPUT ) libcstring_system_character_t guid_string[ 48 ]; libfguid_identifier_t *guid = NULL; uint64_t value_64bit = 0; int result = 0; #endif if( store_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid store block.", function ); return( -1 ); } if( store_block->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid store block - missing data.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading store block at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, file_offset, file_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek store block offset: %" PRIi64 ".", function, file_offset ); return( -1 ); } read_count = libbfio_handle_read_buffer( file_io_handle, store_block->data, store_block->data_size, error ); if( read_count != (ssize_t) store_block->data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read block data.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: store block header:\n", function ); libcnotify_print_data( store_block->data, sizeof( vshadow_store_block_header_t ), LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif if( memory_compare( ( (vshadow_store_block_header_t *) store_block->data )->identifier, vshadow_vss_identifier, 8 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: invalid store block list header identifier.", function ); return( -1 ); } byte_stream_copy_to_uint32_little_endian( ( (vshadow_store_block_header_t *) store_block->data )->version, store_block->version ); byte_stream_copy_to_uint32_little_endian( ( (vshadow_store_block_header_t *) store_block->data )->record_type, store_block->record_type ); byte_stream_copy_to_uint64_little_endian( ( (vshadow_store_block_header_t *) store_block->data )->relative_offset, store_block->relative_offset ); byte_stream_copy_to_uint64_little_endian( ( (vshadow_store_block_header_t *) store_block->data )->offset, store_block->offset ); byte_stream_copy_to_uint64_little_endian( ( (vshadow_store_block_header_t *) store_block->data )->next_offset, store_block->next_offset ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfguid_identifier_initialize( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create GUID.", function ); return( -1 ); } if( libfguid_identifier_copy_from_byte_stream( guid, ( (vshadow_store_block_header_t *) store_block->data )->identifier, 16, LIBFGUID_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy byte stream to GUID.", function ); return( -1 ); } #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) result = libfguid_identifier_copy_to_utf16_string( guid, (uint16_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #else result = libfguid_identifier_copy_to_utf8_string( guid, (uint8_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy GUID to string.", function ); return( -1 ); } libcnotify_printf( "%s: identifier\t\t\t\t\t: %" PRIs_LIBCSTRING_SYSTEM "\n", function, guid_string ); libcnotify_printf( "%s: version\t\t\t\t\t: %" PRIu32 "\n", function, store_block->version ); libcnotify_printf( "%s: record type\t\t\t\t: %" PRIu32 "\n", function, store_block->record_type ); libcnotify_printf( "%s: relative offset\t\t\t\t: 0x%08" PRIx64 "\n", function, store_block->relative_offset ); libcnotify_printf( "%s: offset\t\t\t\t\t: 0x%08" PRIx64 "\n", function, store_block->offset ); libcnotify_printf( "%s: next offset\t\t\t\t: 0x%08" PRIx64 "\n", function, store_block->next_offset ); byte_stream_copy_to_uint64_little_endian( ( (vshadow_store_block_header_t *) store_block->data )->unknown1, value_64bit ); libcnotify_printf( "%s: unknown1\t\t\t\t\t: %" PRIu64 "\n", function, value_64bit ); libcnotify_printf( "%s: unknown2:\n", function ); libcnotify_print_data( ( (vshadow_store_block_header_t *) store_block->data )->unknown2, 72, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); if( libfguid_identifier_free( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free GUID.", function ); return( -1 ); } } #endif if( store_block->version != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported version: %" PRIu32 ".", function, store_block->version ); return( -1 ); } return( 1 ); }
/* Reads a data descriptor * Returns 1 if successful or -1 on error */ int libwrc_resource_read_data_descriptor( libwrc_internal_resource_t *internal_resource, libwrc_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libwrc_data_descriptor_t *data_descriptor, libcerror_error_t **error ) { uint8_t *resource_data = NULL; static char *function = "libwrc_resource_read_data_descriptor"; off64_t file_offset = 0; size_t resource_data_size = 0; ssize_t read_count = 0; if( internal_resource == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid internal resource.", 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_descriptor == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data descriptor.", function ); return( -1 ); } file_offset = data_descriptor->virtual_address - io_handle->virtual_address; if( libbfio_handle_seek_offset( file_io_handle, file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek resource data offset: %" PRIi64 ".", function, file_offset ); goto on_error; } resource_data_size = (size_t) data_descriptor->size; resource_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * resource_data_size ); if( resource_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create resource data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, resource_data, resource_data_size, error ); if( read_count != (ssize_t) resource_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read resource data.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: resource data:\n", function ); libcnotify_print_data( resource_data, resource_data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif memory_free( resource_data ); return( 1 ); on_error: if( resource_data != NULL ) { memory_free( resource_data ); } return( -1 ); }
/* Reads an allocation table * Returns 1 if successful or -1 on error */ int libpff_allocation_table_read( libcdata_range_list_t *unallocated_block_list, libbfio_handle_t *file_io_handle, off64_t allocation_table_offset, uint8_t file_type, libcerror_error_t **error ) { uint8_t *allocation_table_data = NULL; uint8_t *table_data = NULL; static char *function = "libpff_allocation_table_read"; off64_t back_pointer_offset = 0; off64_t unallocated_offset = 0; size_t read_size = 0; size_t unallocated_size = 0; size_t allocation_block_size = 0; ssize_t read_count = 0; uint32_t stored_checksum = 0; uint32_t calculated_checksum = 0; uint16_t table_data_index = 0; uint16_t table_data_size = 0; uint8_t allocation_table_entry = 0; uint8_t allocation_table_type = 0; uint8_t allocation_table_type_copy = 0; uint8_t bit_index = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint64_t value_64bit = 0; uint16_t value_16bit = 0; #endif if( unallocated_block_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid unallocated block list.", function ); return( -1 ); } if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } if( ( file_type != LIBPFF_FILE_TYPE_32BIT ) && ( file_type != LIBPFF_FILE_TYPE_64BIT ) && ( file_type != LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported file type.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading allocation table at offset: 0x%08" PRIx64 "\n", function, allocation_table_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, allocation_table_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek allocation table offset: 0x%08" PRIx64 ".", function, allocation_table_offset ); goto on_error; } if( file_type == LIBPFF_FILE_TYPE_32BIT ) { read_size = sizeof( pff_allocation_table_32bit_t ); table_data_size = 496; } else if( file_type == LIBPFF_FILE_TYPE_64BIT ) { read_size = sizeof( pff_allocation_table_64bit_t ); table_data_size = 496; } else if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) { read_size = sizeof( pff_allocation_table_64bit_4k_page_t ); table_data_size = 4072; } allocation_table_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * read_size ); if( allocation_table_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create alloction table data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, allocation_table_data, read_size, error ); if( read_count != (ssize_t) read_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read allocation table.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: allocation table:\n", function ); libcnotify_print_data( allocation_table_data, read_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif if( file_type == LIBPFF_FILE_TYPE_32BIT ) { table_data = ( (pff_allocation_table_32bit_t *) allocation_table_data )->data; allocation_table_type = ( (pff_allocation_table_32bit_t *) allocation_table_data )->type; allocation_table_type_copy = ( (pff_allocation_table_32bit_t *) allocation_table_data )->type_copy; byte_stream_copy_to_uint32_little_endian( ( (pff_allocation_table_32bit_t *) allocation_table_data )->back_pointer, back_pointer_offset ); byte_stream_copy_to_uint32_little_endian( ( (pff_allocation_table_32bit_t *) allocation_table_data )->checksum, stored_checksum ); } else if( file_type == LIBPFF_FILE_TYPE_64BIT ) { table_data = ( (pff_allocation_table_64bit_t *) allocation_table_data )->data; allocation_table_type = ( (pff_allocation_table_64bit_t *) allocation_table_data )->type; allocation_table_type_copy = ( (pff_allocation_table_64bit_t *) allocation_table_data )->type_copy; byte_stream_copy_to_uint32_little_endian( ( (pff_allocation_table_64bit_t *) allocation_table_data )->checksum, stored_checksum ); byte_stream_copy_to_uint64_little_endian( ( (pff_allocation_table_64bit_t *) allocation_table_data )->back_pointer, back_pointer_offset ); } else if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) { table_data = ( (pff_allocation_table_64bit_4k_page_t *) allocation_table_data )->data; allocation_table_type = ( (pff_allocation_table_64bit_4k_page_t *) allocation_table_data )->type; allocation_table_type_copy = ( (pff_allocation_table_64bit_4k_page_t *) allocation_table_data )->type_copy; byte_stream_copy_to_uint32_little_endian( ( (pff_allocation_table_64bit_4k_page_t *) allocation_table_data )->checksum, stored_checksum ); byte_stream_copy_to_uint64_little_endian( ( (pff_allocation_table_64bit_4k_page_t *) allocation_table_data )->back_pointer, back_pointer_offset ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: type\t\t: 0x%02" PRIx8 "\n", function, allocation_table_type ); libcnotify_printf( "%s: type copy\t\t: 0x%02" PRIx8 "\n", function, allocation_table_type_copy ); if( file_type == LIBPFF_FILE_TYPE_32BIT ) { byte_stream_copy_to_uint16_little_endian( ( (pff_allocation_table_32bit_t *) allocation_table_data )->signature, value_16bit ); libcnotify_printf( "%s: signature\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "%s: back pointer\t: %" PRIu64 "\n", function, back_pointer_offset ); libcnotify_printf( "%s: checksum\t\t: 0x%" PRIx32 "\n", function, stored_checksum ); } else if( ( file_type == LIBPFF_FILE_TYPE_64BIT ) || ( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) ) { if( file_type == LIBPFF_FILE_TYPE_64BIT ) { byte_stream_copy_to_uint16_little_endian( ( (pff_allocation_table_64bit_t *) allocation_table_data )->signature, value_16bit ); } else { byte_stream_copy_to_uint16_little_endian( ( (pff_allocation_table_64bit_4k_page_t *) allocation_table_data )->signature, value_16bit ); } libcnotify_printf( "%s: signature\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "%s: checksum\t\t: 0x%" PRIx32 "\n", function, stored_checksum ); libcnotify_printf( "%s: back pointer\t: %" PRIu64 "\n", function, back_pointer_offset ); if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) { byte_stream_copy_to_uint64_little_endian( ( (pff_allocation_table_64bit_4k_page_t *) allocation_table_data )->unknown1, value_64bit ); libcnotify_printf( "%s: unknown1\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); } } libcnotify_printf( "\n" ); } #endif if( libfmapi_checksum_calculate_weak_crc32( &calculated_checksum, table_data, (size_t) table_data_size, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to calculate weak CRC-32.", function ); goto on_error; } if( stored_checksum != calculated_checksum ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_INPUT, LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH, "%s: mismatch in checksum ( %" PRIu32 " != %" PRIu32 " ).", function, stored_checksum, calculated_checksum ); /* TODO implement error tollerance */ goto on_error; } if( allocation_table_type != allocation_table_type_copy ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_INPUT, LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH, "%s: mismatch in allocation table type ( 0x%02" PRIx8 " != 0x%02" PRIx8 " ).", function, allocation_table_type, allocation_table_type_copy ); /* TODO implement error tollerance */ goto on_error; } if( ( allocation_table_type != LIBPFF_ALLOCATION_TABLE_TYPE_DATA ) && ( allocation_table_type != LIBPFF_ALLOCATION_TABLE_TYPE_PAGE ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported allocation table type: 0x%08" PRIx32 "", function, allocation_table_type ); /* TODO implement error tollerance */ goto on_error; } if( allocation_table_type == LIBPFF_ALLOCATION_TABLE_TYPE_PAGE ) { /* The page type allocation has not yet been seen i.c.w. 4k pages */ if( file_type == LIBPFF_FILE_TYPE_64BIT_4K_PAGE ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported file type.", function ); goto on_error; } allocation_block_size = 512; back_pointer_offset -= 0x200; } else if( allocation_table_type == LIBPFF_ALLOCATION_TABLE_TYPE_DATA ) { allocation_block_size = 64; } for( table_data_index = 0; table_data_index < table_data_size; table_data_index++ ) { allocation_table_entry = table_data[ table_data_index ]; for( bit_index = 0; bit_index < 8; bit_index++ ) { if( ( allocation_table_entry & 0x80 ) == 0 ) { if( unallocated_size == 0 ) { unallocated_offset = back_pointer_offset; } unallocated_size += allocation_block_size; } else if( unallocated_size > 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unallocated block: 0x%08" PRIx64 " - 0x%08" PRIx64 " (%" PRIu64 ")\n", function, unallocated_offset, unallocated_offset + unallocated_size, unallocated_size ); } #endif if( libcdata_range_list_insert_range( unallocated_block_list, unallocated_offset, unallocated_size, NULL, NULL, NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append unallocated block to list.", function ); goto on_error; } unallocated_size = 0; } allocation_table_entry <<= 1; back_pointer_offset += allocation_block_size; } } if( unallocated_size > 0 ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unallocated block: 0x%08" PRIx64 " - 0x%08" PRIx64 " (%" PRIu64 ")\n", function, unallocated_offset, unallocated_offset + unallocated_size, unallocated_size ); } #endif if( libcdata_range_list_insert_range( unallocated_block_list, unallocated_offset, unallocated_size, NULL, NULL, NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append unallocated block to list.", function ); goto on_error; } unallocated_size = 0; } memory_free( allocation_table_data ); return( 1 ); on_error: if( allocation_table_data != NULL ) { memory_free( allocation_table_data ); } return( -1 ); }
/* Reads the records into the records array * Returns 1 if successful or -1 on error */ int libevt_io_handle_read_records( libevt_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, uint32_t first_record_offset, uint32_t end_of_file_record_offset, libfdata_list_t *records_list, off64_t *last_record_offset, libcerror_error_t **error ) { libevt_record_values_t *record_values = NULL; static char *function = "libevt_io_handle_read_records"; off64_t file_offset = 0; ssize_t read_count = 0; uint32_t record_iterator = 0; uint8_t record_type = 0; int element_index = 0; 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( last_record_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid last record offset.", function ); return( -1 ); } file_offset = (off64_t) first_record_offset; if( ( file_offset < (off64_t) sizeof( evt_file_header_t ) ) || ( (size64_t) file_offset >= io_handle->file_size ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: file offset value out of bounds.", function ); goto on_error; } if( libbfio_handle_seek_offset( file_io_handle, file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek record offset: %" PRIi64 ".", function, file_offset ); goto on_error; } do { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading record: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, record_iterator, file_offset, file_offset ); } #endif if( libevt_record_values_initialize( &record_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create record values.", function ); goto on_error; } *last_record_offset = file_offset; read_count = libevt_record_values_read( record_values, file_io_handle, io_handle, &file_offset, 1, error ); if( read_count == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read record: %" PRIu32 ".", function, record_iterator ); goto on_error; } if( *last_record_offset > file_offset ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: wrapped at offset: 0x%08" PRIx64 ".\n", function, *last_record_offset ); } #endif io_handle->has_wrapped = 1; } record_type = record_values->type; if( record_type == LIBEVT_RECORD_TYPE_EVENT ) { if( libfdata_list_append_element( records_list, &element_index, 0, *last_record_offset, (size64_t) read_count, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append record to records list.", function ); goto on_error; } } if( libevt_record_values_free( &record_values, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free record values.", function ); goto on_error; } if( record_type == LIBEVT_RECORD_TYPE_END_OF_FILE ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: end-of-file record found at offset: 0x%08" PRIx64 ".\n", function, file_offset ); } #endif break; } if( ( file_offset > (off64_t) end_of_file_record_offset ) && ( file_offset < (off64_t) ( end_of_file_record_offset + read_count ) ) ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: file offset: 0x%08" PRIx64 " exceeds end-of-file offset: 0x%08" PRIx64 ".\n", function, file_offset, end_of_file_record_offset ); } #endif break; } record_iterator++; } while( record_type != LIBEVT_RECORD_TYPE_END_OF_FILE ); if( record_type == LIBEVT_RECORD_TYPE_END_OF_FILE ) { if( *last_record_offset != (off64_t) end_of_file_record_offset ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: mismatch in end of file record offset ( %" PRIi64 " != %" PRIu32 " ).\n", function, *last_record_offset, end_of_file_record_offset ); } #endif io_handle->flags |= LIBEVT_IO_HANDLE_FLAG_IS_CORRUPTED; } *last_record_offset += read_count; } if( ( io_handle->has_wrapped != 0 ) && ( ( io_handle->flags & LIBEVT_FILE_FLAG_HAS_WRAPPED ) == 0 ) ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: file has wrapped but file flags indicate otherwise.\n", function ); } #endif io_handle->flags |= LIBEVT_IO_HANDLE_FLAG_IS_CORRUPTED; } return( 1 ); on_error: if( record_values != NULL ) { libevt_record_values_free( &record_values, NULL ); } return( -1 ); }
/* Determines if a file contains an EWF file signature using a Basic File IO (bfio) handle * Returns 1 if true, 0 if not or -1 on error */ int libewf_check_file_signature_file_io_handle( libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { uint8_t signature[ 8 ]; static char *function = "libewf_check_file_signature_file_io_handle"; ssize_t read_count = 0; int file_io_handle_is_open = 0; if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } file_io_handle_is_open = libbfio_handle_is_open( file_io_handle, error ); if( file_io_handle_is_open == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open file.", function ); return( -1 ); } else if( file_io_handle_is_open == 0 ) { if( libbfio_handle_open( file_io_handle, LIBBFIO_OPEN_READ, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open file.", function ); return( -1 ); } } if( libbfio_handle_seek_offset( file_io_handle, 0, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek file header offset: 0.", function ); if( file_io_handle_is_open == 0 ) { libbfio_handle_close( file_io_handle, error ); } return( -1 ); } read_count = libbfio_handle_read_buffer( file_io_handle, signature, 8, error ); if( read_count != 8 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read signature.", function ); libbfio_handle_close( file_io_handle, NULL ); return( -1 ); } if( file_io_handle_is_open == 0 ) { if( libbfio_handle_close( file_io_handle, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close file.", function ); return( -1 ); } } /* The number of EWF segment files will be the largest */ if( memory_compare( ewf1_evf_file_signature, signature, 8 ) == 0 ) { return( 1 ); } else if( memory_compare( ewf1_lvf_file_signature, signature, 8 ) == 0 ) { return( 1 ); } else if( memory_compare( ewf2_evf_file_signature, signature, 8 ) == 0 ) { return( 1 ); } else if( memory_compare( ewf2_lef_file_signature, signature, 8 ) == 0 ) { return( 1 ); } else if( memory_compare( ewf1_dvf_file_signature, signature, 8 ) == 0 ) { return( 1 ); } return( 0 ); }
/* Scans for the end-of-file record and adjusts the offsets accordingly * Returns 1 if successful, 0 if not or -1 on error */ int libevt_io_handle_end_of_file_record_scan( libevt_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, uint32_t *first_record_offset, uint32_t *end_of_file_record_offset, libcerror_error_t **error ) { uint8_t *scan_block = NULL; static char *function = "libevt_io_handle_end_of_file_record_scan"; off64_t file_offset = 0; off64_t initial_file_offset = 0; size_t read_size = 0; size_t scan_block_offset = 0; size_t scan_block_size = 8192; ssize_t read_count = 0; uint8_t scan_state = LIBEVT_RECOVER_SCAN_STATE_START; uint8_t scan_has_wrapped = 0; 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( first_record_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid first record offset.", function ); return( -1 ); } if( end_of_file_record_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid end of file record offset.", function ); return( -1 ); } scan_block = (uint8_t *) memory_allocate( sizeof( uint8_t ) * scan_block_size ); if( scan_block == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create scan block.", function ); goto on_error; } /* If the file has wrapped start looking for the end-of-file record after the end-of-file record offset */ file_offset = (off64_t) *end_of_file_record_offset; if( ( file_offset < (off64_t) sizeof( evt_file_header_t ) ) || ( (size64_t) file_offset >= io_handle->file_size ) ) { file_offset = (off64_t) sizeof( evt_file_header_t ); } initial_file_offset = file_offset; if( libbfio_handle_seek_offset( file_io_handle, file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek scan block offset: %" PRIi64 ".", function, file_offset ); goto on_error; } do { if( ( (size64_t) file_offset + scan_block_size ) > io_handle->file_size ) { read_size = (size_t) ( io_handle->file_size - file_offset ); } else { read_size = scan_block_size; } read_count = libbfio_handle_read_buffer( file_io_handle, scan_block, read_size, error ); if( read_count != (ssize_t) read_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read scan block at offset: %" PRIi64 ".", function, file_offset ); goto on_error; } file_offset += read_count; for( scan_block_offset = 0; scan_block_offset < read_size; scan_block_offset += 4 ) { if( scan_state == LIBEVT_RECOVER_SCAN_STATE_START ) { if( memory_compare( &( scan_block[ scan_block_offset ] ), evt_end_of_file_record_signature1, 4 ) == 0 ) { scan_state = LIBEVT_RECOVER_SCAN_STATE_FOUND_EOF_SIGNATURE1; } } else if( scan_state == LIBEVT_RECOVER_SCAN_STATE_FOUND_EOF_SIGNATURE1 ) { if( memory_compare( &( scan_block[ scan_block_offset ] ), evt_end_of_file_record_signature2, 4 ) == 0 ) { scan_state = LIBEVT_RECOVER_SCAN_STATE_FOUND_EOF_SIGNATURE2; } else { scan_state = LIBEVT_RECOVER_SCAN_STATE_START; } } else if( scan_state == LIBEVT_RECOVER_SCAN_STATE_FOUND_EOF_SIGNATURE2 ) { if( memory_compare( &( scan_block[ scan_block_offset ] ), evt_end_of_file_record_signature3, 4 ) == 0 ) { scan_state = LIBEVT_RECOVER_SCAN_STATE_FOUND_EOF_SIGNATURE3; } else { scan_state = LIBEVT_RECOVER_SCAN_STATE_START; } } else if( scan_state == LIBEVT_RECOVER_SCAN_STATE_FOUND_EOF_SIGNATURE3 ) { if( memory_compare( &( scan_block[ scan_block_offset ] ), evt_end_of_file_record_signature4, 4 ) == 0 ) { *end_of_file_record_offset = (uint32_t) ( file_offset - read_count + scan_block_offset - 16 ); scan_state = LIBEVT_RECOVER_SCAN_STATE_FOUND_EOF_SIGNATURE4; } else { scan_state = LIBEVT_RECOVER_SCAN_STATE_START; } } else if( scan_state == LIBEVT_RECOVER_SCAN_STATE_FOUND_EOF_SIGNATURE4 ) { if( memory_compare( &( scan_block[ scan_block_offset ] ), evt_file_signature, 4 ) == 0 ) { *first_record_offset = (uint32_t) ( file_offset - read_count + scan_block_offset - 4 ); scan_state = LIBEVT_RECOVER_SCAN_STATE_FOUND_RECORD_SIGNATURE; break; } } } if( scan_state == LIBEVT_RECOVER_SCAN_STATE_FOUND_RECORD_SIGNATURE ) { break; } if( (size64_t) file_offset >= io_handle->file_size ) { if( libbfio_handle_seek_offset( file_io_handle, (off64_t) sizeof( evt_file_header_t ), SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek scan block offset: %" PRIzd ".", function, sizeof( evt_file_header_t ) ); goto on_error; } file_offset = (off64_t) sizeof( evt_file_header_t ); scan_has_wrapped = 1; } } while( ( scan_has_wrapped == 0 ) || ( file_offset < initial_file_offset ) ); memory_free( scan_block ); scan_block = NULL; if( scan_state == LIBEVT_RECOVER_SCAN_STATE_FOUND_RECORD_SIGNATURE ) { return( 1 ); } return( 0 ); on_error: if( scan_block != NULL ) { memory_free( scan_block ); } return( -1 ); }
/* Reads the volume header * Returns 1 if successful or -1 on error */ int libbde_io_handle_read_volume_header( libbde_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, off64_t file_offset, libcerror_error_t **error ) { uint8_t *volume_header_data = NULL; static char *function = "libbde_io_handle_read_volume_header"; size_t read_size = 512; ssize_t read_count = 0; uint64_t total_number_of_sectors = 0; #if defined( HAVE_DEBUG_OUTPUT ) libcstring_system_character_t guid_string[ 48 ]; libfguid_identifier_t *guid = NULL; uint64_t value_64bit = 0; uint32_t value_32bit = 0; uint16_t value_16bit = 0; int result = 0; #endif if( io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid IO handle.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading volume header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, file_offset, file_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek volume header offset: %" PRIi64 ".", function, file_offset ); goto on_error; } volume_header_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * read_size ); if( volume_header_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create volume header data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, volume_header_data, read_size, error ); if( read_count != (ssize_t) read_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read volume header data.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: volume header data:\n", function ); libcnotify_print_data( volume_header_data, read_size, 0 ); } #endif if( memory_compare( volume_header_data, bde_boot_entry_point_vista, 3 ) == 0 ) { io_handle->version = LIBBDE_VERSION_WINDOWS_VISTA; } else if( memory_compare( volume_header_data, bde_boot_entry_point_win7, 3 ) == 0 ) { if( memory_compare( ( (bde_volume_header_windows_7_t *) volume_header_data )->identifier, bde_identifier, 16 ) == 0 ) { io_handle->version = LIBBDE_VERSION_WINDOWS_7; } else if( memory_compare( ( (bde_volume_header_to_go_t *) volume_header_data )->identifier, bde_identifier, 16 ) == 0 ) { io_handle->version = LIBBDE_VERSION_TO_GO; } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported identifier.", function ); goto on_error; } } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported volume boot entry point.", function ); goto on_error; } if( ( io_handle->version == LIBBDE_VERSION_WINDOWS_VISTA ) || ( io_handle->version == LIBBDE_VERSION_WINDOWS_7 ) ) { if( memory_compare( &( volume_header_data[ 3 ] ), bde_signature, 8 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: invalid volume signature.", function ); goto on_error; } } byte_stream_copy_to_uint16_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->bytes_per_sector, io_handle->bytes_per_sector ); io_handle->sectors_per_cluster_block = ( (bde_volume_header_windows_vista_t *) volume_header_data )->sectors_per_cluster_block; byte_stream_copy_to_uint16_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->total_number_of_sectors_16bit, total_number_of_sectors ); if( total_number_of_sectors == 0 ) { byte_stream_copy_to_uint32_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->total_number_of_sectors_32bit, total_number_of_sectors ); } if( io_handle->version == LIBBDE_VERSION_WINDOWS_VISTA ) { byte_stream_copy_to_uint64_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->first_metadata_cluster_block_number, io_handle->first_metadata_offset ); if( total_number_of_sectors == 0 ) { byte_stream_copy_to_uint64_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->total_number_of_sectors_64bit, total_number_of_sectors ); } } else if( io_handle->version == LIBBDE_VERSION_WINDOWS_7 ) { byte_stream_copy_to_uint64_little_endian( ( (bde_volume_header_windows_7_t *) volume_header_data )->first_metadata_offset, io_handle->first_metadata_offset ); byte_stream_copy_to_uint64_little_endian( ( (bde_volume_header_windows_7_t *) volume_header_data )->second_metadata_offset, io_handle->second_metadata_offset ); byte_stream_copy_to_uint64_little_endian( ( (bde_volume_header_windows_7_t *) volume_header_data )->third_metadata_offset, io_handle->third_metadata_offset ); } else if( io_handle->version == LIBBDE_VERSION_TO_GO ) { byte_stream_copy_to_uint64_little_endian( ( (bde_volume_header_to_go_t *) volume_header_data )->first_metadata_offset, io_handle->first_metadata_offset ); byte_stream_copy_to_uint64_little_endian( ( (bde_volume_header_to_go_t *) volume_header_data )->second_metadata_offset, io_handle->second_metadata_offset ); byte_stream_copy_to_uint64_little_endian( ( (bde_volume_header_to_go_t *) volume_header_data )->third_metadata_offset, io_handle->third_metadata_offset ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: boot entry point:\n", function ); libcnotify_print_data( volume_header_data, 3, 0 ); libcnotify_printf( "%s: signature\t\t\t\t: %c%c%c%c%c%c%c%c\n", function, volume_header_data[ 3 ], volume_header_data[ 4 ], volume_header_data[ 5 ], volume_header_data[ 6 ], volume_header_data[ 7 ], volume_header_data[ 8 ], volume_header_data[ 9 ], volume_header_data[ 10 ] ); libcnotify_printf( "%s: bytes per sector\t\t\t: %" PRIu16 "\n", function, io_handle->bytes_per_sector ); libcnotify_printf( "%s: sectors per cluster block\t\t: %" PRIu8 "\n", function, io_handle->sectors_per_cluster_block ); libcnotify_printf( "%s: unknown1\n", function ); libcnotify_print_data( ( (bde_volume_header_windows_vista_t *) volume_header_data )->unknown1, 5, 0 ); byte_stream_copy_to_uint16_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->total_number_of_sectors_16bit, value_16bit ); libcnotify_printf( "%s: total number of sectors (16-bit)\t: %" PRIu16 "\n", function, value_16bit ); libcnotify_printf( "%s: media descriptor\t\t\t: 0x%02" PRIx8 "\n", function, ( (bde_volume_header_windows_vista_t *) volume_header_data )->media_descriptor ); byte_stream_copy_to_uint16_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->unknown2, value_16bit ); libcnotify_printf( "%s: unknown2\t\t\t\t: %" PRIu16 "\n", function, value_16bit ); byte_stream_copy_to_uint16_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->sectors_per_track, value_16bit ); libcnotify_printf( "%s: sectors per track\t\t\t: %" PRIu16 "\n", function, value_16bit ); byte_stream_copy_to_uint16_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->number_of_heads, value_16bit ); libcnotify_printf( "%s: number of heads\t\t\t: %" PRIu16 "\n", function, value_16bit ); byte_stream_copy_to_uint32_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->number_of_hidden_sectors, value_32bit ); libcnotify_printf( "%s: number of hidden sectors\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->total_number_of_sectors_32bit, value_32bit ); libcnotify_printf( "%s: total number of sectors (32-bit)\t: %" PRIu32 "\n", function, value_32bit ); if( io_handle->version == LIBBDE_VERSION_WINDOWS_VISTA ) { byte_stream_copy_to_uint32_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->unknown4, value_32bit ); libcnotify_printf( "%s: unknown4\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", function, value_32bit, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->total_number_of_sectors_64bit, value_64bit ); libcnotify_printf( "%s: total number of sectors (64-bit)\t: %" PRIu64 "\n", function, value_64bit ); byte_stream_copy_to_uint64_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->mft_cluster_block_number, value_64bit ); libcnotify_printf( "%s: MFT cluster block number\t\t: %" PRIu64 "\n", function, value_64bit ); libcnotify_printf( "%s: first metadata cluster block\t: 0x%08" PRIx64 "\n", function, io_handle->first_metadata_offset ); byte_stream_copy_to_uint32_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->mft_entry_size, value_32bit ); libcnotify_printf( "%s: MFT entry size\t\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->index_entry_size, value_32bit ); libcnotify_printf( "%s: index entry size\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint64_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->volume_serial_number, value_64bit ); libcnotify_printf( "%s: volume serial number\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); byte_stream_copy_to_uint32_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->checksum, value_32bit ); libcnotify_printf( "%s: checksum\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: bootcode\n", function ); libcnotify_print_data( ( (bde_volume_header_windows_vista_t *) volume_header_data )->bootcode, 426, 0 ); } else if( ( io_handle->version == LIBBDE_VERSION_WINDOWS_7 ) || ( io_handle->version == LIBBDE_VERSION_TO_GO ) ) { libcnotify_printf( "%s: unknown4:\n", function ); libcnotify_print_data( ( (bde_volume_header_windows_7_t *) volume_header_data )->unknown4, 31, 0 ); byte_stream_copy_to_uint32_little_endian( ( (bde_volume_header_windows_7_t *) volume_header_data )->volume_serial_number, value_64bit ); libcnotify_printf( "%s: volume serial number\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: volume label\t\t\t: %c%c%c%c%c%c%c%c%c%c%c\n", function, ( (bde_volume_header_windows_7_t *) volume_header_data )->volume_label[ 0 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->volume_label[ 1 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->volume_label[ 2 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->volume_label[ 3 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->volume_label[ 4 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->volume_label[ 5 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->volume_label[ 6 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->volume_label[ 7 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->volume_label[ 8 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->volume_label[ 9 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->volume_label[ 10 ] ); libcnotify_printf( "%s: file system signature\t\t: %c%c%c%c%c%c%c%c\n", function, ( (bde_volume_header_windows_7_t *) volume_header_data )->file_system_signature[ 0 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->file_system_signature[ 1 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->file_system_signature[ 2 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->file_system_signature[ 3 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->file_system_signature[ 4 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->file_system_signature[ 5 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->file_system_signature[ 6 ], ( (bde_volume_header_windows_7_t *) volume_header_data )->file_system_signature[ 7 ] ); } if( io_handle->version == LIBBDE_VERSION_WINDOWS_7 ) { libcnotify_printf( "%s: bootcode\n", function ); libcnotify_print_data( ( (bde_volume_header_windows_7_t *) volume_header_data )->bootcode, 47, 0 ); if( libfguid_identifier_initialize( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create GUID.", function ); goto on_error; } if( libfguid_identifier_copy_from_byte_stream( guid, ( (bde_volume_header_windows_7_t *) volume_header_data )->identifier, 16, LIBFGUID_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy byte stream to GUID.", function ); goto on_error; } #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) result = libfguid_identifier_copy_to_utf16_string( guid, (uint16_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #else result = libfguid_identifier_copy_to_utf8_string( guid, (uint8_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy GUID to string.", function ); goto on_error; } libcnotify_printf( "%s: identifier\t\t\t\t: %" PRIs_LIBCSTRING_SYSTEM "\n", function, guid_string ); if( libfguid_identifier_free( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free GUID.", function ); goto on_error; } } else if( io_handle->version == LIBBDE_VERSION_TO_GO ) { libcnotify_printf( "%s: bootcode\n", function ); libcnotify_print_data( ( (bde_volume_header_to_go_t *) volume_header_data )->bootcode, 335, 0 ); if( libfguid_identifier_initialize( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create GUID.", function ); goto on_error; } if( libfguid_identifier_copy_from_byte_stream( guid, ( (bde_volume_header_to_go_t *) volume_header_data )->identifier, 16, LIBFGUID_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy byte stream to GUID.", function ); goto on_error; } #if defined( LIBCSTRING_HAVE_WIDE_SYSTEM_CHARACTER ) result = libfguid_identifier_copy_to_utf16_string( guid, (uint16_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #else result = libfguid_identifier_copy_to_utf8_string( guid, (uint8_t *) guid_string, 48, LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_COPY_FAILED, "%s: unable to copy GUID to string.", function ); goto on_error; } libcnotify_printf( "%s: identifier\t\t\t\t: %" PRIs_LIBCSTRING_SYSTEM "\n", function, guid_string ); if( libfguid_identifier_free( &guid, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free GUID.", function ); goto on_error; } } if( ( io_handle->version == LIBBDE_VERSION_WINDOWS_7 ) || ( io_handle->version == LIBBDE_VERSION_TO_GO ) ) { libcnotify_printf( "%s: first metadata offset\t\t: 0x%08" PRIx64 "\n", function, io_handle->first_metadata_offset ); libcnotify_printf( "%s: second metadata offset\t\t: 0x%08" PRIx64 "\n", function, io_handle->second_metadata_offset ); libcnotify_printf( "%s: third metadata offset\t\t: 0x%08" PRIx64 "\n", function, io_handle->third_metadata_offset ); } if( io_handle->version == LIBBDE_VERSION_WINDOWS_7 ) { libcnotify_printf( "%s: unknown5:\n", function ); libcnotify_print_data( ( (bde_volume_header_windows_7_t *) volume_header_data )->unknown5, 310, 0 ); } else if( io_handle->version == LIBBDE_VERSION_TO_GO ) { libcnotify_printf( "%s: unknown5:\n", function ); libcnotify_print_data( ( (bde_volume_header_to_go_t *) volume_header_data )->unknown5, 46, 0 ); } byte_stream_copy_to_uint16_little_endian( ( (bde_volume_header_windows_vista_t *) volume_header_data )->sector_signature, value_16bit ); libcnotify_printf( "%s: sector signature\t\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "\n" ); } #endif if( total_number_of_sectors != 0 ) { io_handle->volume_size = total_number_of_sectors; io_handle->volume_size *= io_handle->bytes_per_sector; } if( io_handle->version == LIBBDE_VERSION_WINDOWS_VISTA ) { io_handle->first_metadata_offset *= io_handle->sectors_per_cluster_block; io_handle->first_metadata_offset *= io_handle->bytes_per_sector; io_handle->metadata_size = 16384; } else if( ( io_handle->version == LIBBDE_VERSION_WINDOWS_7 ) || ( io_handle->version == LIBBDE_VERSION_TO_GO ) ) { io_handle->metadata_size = 65536; } memory_free( volume_header_data ); volume_header_data = NULL; return( 1 ); on_error: #if defined( HAVE_DEBUG_OUTPUT ) if( guid != NULL ) { libfguid_identifier_free( &guid, NULL ); } #endif if( volume_header_data != NULL ) { memory_free( volume_header_data ); } return( -1 ); }
/* Reads the data list of a descriptor * Returns 1 if successful or -1 on error */ int libpff_io_handle_read_descriptor_data_list( libpff_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, libpff_offsets_index_t *offsets_index, uint32_t descriptor_identifier, uint64_t data_identifier, uint8_t recovered, int recovered_value_index, libfdata_list_t **descriptor_data_list, libfcache_cache_t **descriptor_data_cache, libcerror_error_t **error ) { libpff_data_array_t *data_array = NULL; libpff_data_block_t *data_block = NULL; libpff_index_value_t *offset_index_value = NULL; static char *function = "libpff_io_handle_read_descriptor_data_list"; int element_index = 0; 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( descriptor_data_list == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid descriptor data list.", function ); return( -1 ); } if( *descriptor_data_list != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: descriptor data list already set.", function ); return( -1 ); } if( descriptor_data_cache == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid descriptor data cache.", function ); return( -1 ); } if( *descriptor_data_cache != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: descriptor data cache already set.", function ); return( -1 ); } if( libpff_offsets_index_get_index_value_by_identifier( offsets_index, file_io_handle, data_identifier, recovered, recovered_value_index, &offset_index_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to find offset index value identifier: %" PRIu64 ".", function, data_identifier ); goto on_error; } if( offset_index_value == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid offset index value.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: identifier: %" PRIu64 " (%s) at offset: %" PRIi64 " of size: %" PRIu32 "\n", function, offset_index_value->identifier, ( ( offset_index_value->identifier & LIBPFF_OFFSET_INDEX_IDENTIFIER_FLAG_INTERNAL ) ? "internal" : "external" ), offset_index_value->file_offset, offset_index_value->data_size ); } #endif if( offset_index_value->file_offset <= 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid offset index value - file offset value out of bounds.", function ); goto on_error; } if( offset_index_value->data_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid offset index value - data size value value out of bounds.", function ); goto on_error; } #if UINT32_MAX > SSIZE_MAX if( offset_index_value->data_size > (size32_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid offset index value - data size value exceeds maximum.", function ); goto on_error; } #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading data block at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, offset_index_value->file_offset, offset_index_value->file_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, offset_index_value->file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek data block offset: %" PRIi64 ".", function, offset_index_value->file_offset ); goto on_error; } if( libpff_data_block_initialize( &data_block, io_handle, descriptor_identifier, data_identifier, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data block.", function ); goto on_error; } if( libpff_data_block_read( data_block, file_io_handle, offset_index_value->data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read data block at offset: %" PRIi64 ".", function, offset_index_value->file_offset ); goto on_error; } /* Check if the data block contains a data array * The data array should have the internal flag set in the (data) offset index identifier * The data array starts with 0x01 followed by either 0x01 or 0x02 */ if( ( ( data_identifier & (uint64_t) LIBPFF_OFFSET_INDEX_IDENTIFIER_FLAG_INTERNAL ) != 0 ) && ( ( data_block->data[ 0 ] == 0x01 ) && ( ( data_block->data[ 1 ] == 0x01 ) || ( data_block->data[ 1 ] == 0x02 ) ) ) ) { if( libpff_data_array_initialize( &data_array, descriptor_identifier, data_identifier, io_handle, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create data array.", function ); goto on_error; } if( libfdata_list_initialize( descriptor_data_list, (intptr_t *) data_array, (int (*)(intptr_t **, libcerror_error_t **)) &libpff_data_array_free, (int (*)(intptr_t **, intptr_t *, libcerror_error_t **)) &libpff_data_array_clone, (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfcache_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libpff_data_array_read_element_data, NULL, LIBFDATA_DATA_HANDLE_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create descriptor data list.", function ); goto on_error; } /* The data_array is now managed by the list */ if( libpff_data_array_read( data_array, io_handle, file_io_handle, offsets_index, *descriptor_data_list, recovered, data_block->data, (size_t) offset_index_value->data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read data array.", function ); data_array = NULL; goto on_error; } if( libpff_data_block_free( &data_block, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free data block.", function ); data_array = NULL; goto on_error; } if( libfcache_cache_initialize( descriptor_data_cache, LIBPFF_MAXIMUM_CACHE_ENTRIES_DATA_ARRAY, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create descriptor data cache.", function ); data_array = NULL; goto on_error; } } else { if( libpff_data_block_decrypt_data( data_block, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ENCRYPTION, LIBCERROR_ENCRYPTION_ERROR_DECRYPT_FAILED, "%s: unable to decrypt data block data.", function ); goto on_error; } /* TODO change data block not be a data handle ? pass a descriptor instead ? */ if( libfdata_list_initialize( descriptor_data_list, (intptr_t *) data_block, (int (*)(intptr_t **, libcerror_error_t **)) &libpff_data_block_free, (int (*)(intptr_t **, intptr_t *, libcerror_error_t **)) &libpff_data_block_clone, (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfcache_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libpff_data_block_read_element_data, NULL, LIBFDATA_DATA_HANDLE_FLAG_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create descriptor data list.", function ); goto on_error; } /* The data_block is now managed by the list */ if( libfdata_list_append_element_with_mapped_size( *descriptor_data_list, &element_index, 0, offset_index_value->file_offset, (size64_t) offset_index_value->data_size, 0, (size_t) data_block->uncompressed_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to append data list element.", function ); data_block = NULL; goto on_error; } if( libfcache_cache_initialize( descriptor_data_cache, LIBPFF_MAXIMUM_CACHE_ENTRIES_DATA_BLOCK, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create descriptor data cache.", function ); data_block = NULL; goto on_error; } /* The data block is managed by the list and should not be managed by the cache as well */ if( libfdata_list_set_element_value_by_index( *descriptor_data_list, (intptr_t *) file_io_handle, *descriptor_data_cache, 0, (intptr_t *) data_block, (int (*)(intptr_t **, libcerror_error_t **)) &libpff_data_block_free, LIBFDATA_LIST_ELEMENT_VALUE_FLAG_NON_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set data list element: 0.", function ); data_block = NULL; goto on_error; } } return( 1 ); on_error: if( *descriptor_data_cache != NULL ) { libfcache_cache_free( descriptor_data_cache, NULL ); } if( *descriptor_data_list != NULL ) { libfdata_list_free( descriptor_data_list, NULL ); } if( data_array != NULL ) { libpff_data_array_free( &data_array, NULL ); } if( data_block != NULL ) { libpff_data_block_free( &data_block, NULL ); } return( -1 ); }
/* Reads the file header * Returns 1 if successful or -1 on error */ int libmdmp_io_handle_read_file_header( libmdmp_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, uint32_t *streams_directory_offset, uint32_t *number_of_streams, libcerror_error_t **error ) { mdmp_file_header_t file_header; static char *function = "libmdmp_io_handle_read_file_header"; ssize_t read_count = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint32_t value_32bit = 0; uint16_t value_16bit = 0; #endif 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( streams_directory_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid streams directory offset.", function ); return( -1 ); } if( number_of_streams == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid number of streams.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading file header at offset: 0 (0x00000000)\n", function ); } #endif if( libbfio_handle_seek_offset( file_io_handle, 0, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek file header offset: 0.", function ); return( -1 ); } read_count = libbfio_handle_read_buffer( file_io_handle, (uint8_t *) &file_header, sizeof( mdmp_file_header_t ), error ); if( read_count != (ssize_t) sizeof( mdmp_file_header_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read file header data.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: file header data:\n", function ); libcnotify_print_data( (uint8_t *) &file_header, sizeof( mdmp_file_header_t ), 0 ); } #endif if( memory_compare( file_header.signature, mdmp_file_signature, 4 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: invalid signature.", function ); return( -1 ); } byte_stream_copy_to_uint16_little_endian( file_header.version, io_handle->version ); byte_stream_copy_to_uint32_little_endian( file_header.number_of_streams, *number_of_streams ); byte_stream_copy_to_uint32_little_endian( file_header.streams_directory_rva, *streams_directory_offset ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: signature\t\t\t\t: %c%c%c%c\n", function, file_header.signature[ 0 ], file_header.signature[ 1 ], file_header.signature[ 2 ], file_header.signature[ 3 ] ); libcnotify_printf( "%s: version\t\t\t\t: 0x%04" PRIx16 "\n", function, io_handle->version ); byte_stream_copy_to_uint16_little_endian( file_header.implementation_version, value_16bit ); libcnotify_printf( "%s: implementation version\t\t: 0x%04" PRIx16 "\n", function, value_16bit ); libcnotify_printf( "%s: number of streams\t\t\t: 0x%08" PRIx32 "\n", function, *number_of_streams ); libcnotify_printf( "%s: streams directory RVA\t\t: 0x%08" PRIx32 "\n", function, *streams_directory_offset ); byte_stream_copy_to_uint32_little_endian( file_header.checksum, value_32bit ); libcnotify_printf( "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); /* TODO print date time value */ byte_stream_copy_to_uint32_little_endian( file_header.timestamp, value_32bit ); libcnotify_printf( "%s: timestamp\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( file_header.file_flags, value_32bit ); libcnotify_printf( "%s: file flags\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libmdmp_debug_print_file_flags( value_32bit ); libcnotify_printf( "\n" ); libcnotify_printf( "\n" ); } #endif return( 1 ); }
/* Reads string values * Returns 1 if successful or -1 on error */ int libwrc_string_values_read( libwrc_language_entry_t *language_entry, libwrc_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, uint32_t identifier, libwrc_data_descriptor_t *data_descriptor, libcerror_error_t **error ) { libfvalue_value_t *string_value = NULL; uint8_t *resource_data = NULL; uint8_t *string_resource_data = NULL; static char *function = "libwrc_string_values_read"; off64_t file_offset = 0; size_t resource_data_size = 0; ssize_t read_count = 0; uint32_t string_identifier = 0; uint32_t string_index = 0; uint32_t string_size = 0; int value_index = 0; if( language_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid language entry.", 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_descriptor == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid data descriptor.", function ); return( -1 ); } file_offset = data_descriptor->virtual_address - io_handle->virtual_address; if( libbfio_handle_seek_offset( file_io_handle, file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek resource data offset: %" PRIi64 ".", function, file_offset ); goto on_error; } resource_data_size = (size_t) data_descriptor->size; resource_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * resource_data_size ); if( resource_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create resource data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, resource_data, resource_data_size, error ); if( read_count != (ssize_t) resource_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read resource data.", function ); goto on_error; } string_resource_data = resource_data; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: resource data:\n", function ); libcnotify_print_data( string_resource_data, resource_data_size, 0 ); } #endif while( resource_data_size > 0 ) { byte_stream_copy_to_uint16_little_endian( string_resource_data, string_size ); string_resource_data += sizeof( uint16_t ); resource_data_size -= sizeof( uint16_t ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: string: %02" PRIu32 " length\t\t\t\t: %" PRIu32 "\n", function, string_index, string_size ); } #endif if( string_size > 0 ) { string_identifier = ( identifier << 4 ) | string_index; string_size *= 2; if( string_size > resource_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: string size value out of bound.", function ); goto on_error; } if( libfvalue_value_type_initialize( &string_value, LIBFVALUE_VALUE_TYPE_STRING_UTF16, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create string value.", function ); goto on_error; } if( libfvalue_value_set_identifier( string_value, (uint8_t *) &string_identifier, 4, LIBFVALUE_VALUE_FLAG_IDENTIFIER_MANAGED, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to set identifier of string value.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: string: %02" PRIu32 " data:\n", function, string_index ); libcnotify_print_data( string_resource_data, (size_t) string_size, 0 ); } #endif if( libfvalue_value_set_data( string_value, string_resource_data, (size_t) string_size, LIBFVALUE_CODEPAGE_UTF16_LITTLE_ENDIAN, 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 of string value.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: string: %02" PRIu32 " value\t\t\t\t: ", function, string_index ); if( libfvalue_value_print( string_value, 0, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print string value.", function ); goto on_error; } libcnotify_printf( "\n" ); } #endif string_resource_data += (size_t) string_size; resource_data_size -= (size_t) string_size; if( libwrc_language_entry_append_value( language_entry, &value_index, (intptr_t *) string_value, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append string value.", function ); goto on_error; } string_value = NULL; } #if defined( HAVE_DEBUG_OUTPUT ) else if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n" ); } #endif string_index++; } memory_free( resource_data ); /* TODO validate if number of strings is 16 ? */ return( 1 ); on_error: if( string_value != NULL ) { libfvalue_value_free( &string_value, NULL ); } if( resource_data != NULL ) { memory_free( resource_data ); } return( -1 ); }
/* Reads the streams directory * Returns 1 if successful or -1 on error */ int libmdmp_io_handle_read_streams_directory( libmdmp_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, uint32_t streams_directory_offset, uint32_t number_of_streams, libcdata_array_t *streams_array, libcerror_error_t **error ) { libmdmp_stream_descriptor_t *stream_descriptor = NULL; uint8_t *streams_directory_data = NULL; uint8_t *streams_directory_entry_data = NULL; static char *function = "libmdmp_io_handle_read_streams_directory"; size_t streams_directory_data_size = 0; ssize_t read_count = 0; uint32_t stream_data_offset = 0; uint32_t stream_data_size = 0; uint32_t stream_index = 0; int entry_index = 0; int result = 0; 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 defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading streams directory at offset: %" PRIu32 " (0x%08" PRIx32 ")\n", function, streams_directory_offset, streams_directory_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, streams_directory_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek streams directory offset: %" PRIu32 " (0x%08" PRIx32 ").", function ); goto on_error; } streams_directory_data_size = sizeof( mdmp_streams_directory_entry_t ) * number_of_streams; if( streams_directory_data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: invalid streams directory data size value out of bounds.", function ); goto on_error; } streams_directory_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * streams_directory_data_size ); if( streams_directory_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create streams directory data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, streams_directory_data, streams_directory_data_size, error ); if( read_count != (ssize_t) streams_directory_data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read streams directory data.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: streams directory data:\n", function ); libcnotify_print_data( streams_directory_data, streams_directory_data_size, 0 ); } #endif streams_directory_entry_data = streams_directory_data; for( stream_index = 0; stream_index < number_of_streams; stream_index++ ) { if( stream_descriptor == NULL ) { if( libmdmp_stream_descriptor_initialize( &stream_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create stream descriptor.", function ); goto on_error; } } byte_stream_copy_to_uint32_little_endian( ( (mdmp_streams_directory_entry_t *) streams_directory_entry_data )->stream_type, stream_descriptor->type ); byte_stream_copy_to_uint32_little_endian( ( (mdmp_streams_directory_entry_t *) streams_directory_entry_data )->stream_data_size, stream_data_size ); byte_stream_copy_to_uint32_little_endian( ( (mdmp_streams_directory_entry_t *) streams_directory_entry_data )->stream_data_rva, stream_data_offset ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: stream: %02" PRIu32 " type\t\t: %" PRIu32 " (%s)\n", function, stream_index, stream_descriptor->type, libmdmp_debug_get_stream_type( stream_descriptor->type ) ); libcnotify_printf( "%s: stream: %02" PRIu32 " data size\t\t: %" PRIu32 "\n", function, stream_index, stream_data_size ); libcnotify_printf( "%s: stream: %02" PRIu32 " RVA\t\t: 0x%08" PRIx32 "\n", function, stream_index, stream_data_offset ); } #endif result = memory_compare( streams_directory_entry_data, empty_streams_directory_entry, sizeof( mdmp_streams_directory_entry_t ) ); streams_directory_entry_data += sizeof( mdmp_streams_directory_entry_t ); if( result != 0 ) { if( libmdmp_stream_descriptor_set_data_range( stream_descriptor, (off64_t) stream_data_offset, (size64_t) stream_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set data range in stream descriptor.", function ); goto on_error; } if( libcdata_array_append_entry( streams_array, &entry_index, (intptr_t *) stream_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append stream descriptor to sections array.", function ); goto on_error; } stream_descriptor = NULL; } } if( stream_descriptor != NULL ) { if( libmdmp_stream_descriptor_free( &stream_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free stream descriptor.", function ); goto on_error; } } memory_free( streams_directory_data ); return( 1 ); on_error: if( stream_descriptor != NULL ) { libmdmp_stream_descriptor_free( &stream_descriptor, NULL ); } if( streams_directory_data != NULL ) { memory_free( streams_directory_data ); } return( -1 ); }
/* Reads a hash table * Returns 1 if successful or -1 on error */ int libmsiecf_hash_table_read( libcdata_array_t *hash_table, off64_t *next_hash_table_offset, libbfio_handle_t *file_io_handle, off64_t hash_table_offset, size32_t block_size, libcerror_error_t **error ) { msiecf_hash_record_header_t hash_record_header; uint8_t *hash_record_data = NULL; uint8_t *entry_data = NULL; static char *function = "libmsiecf_hash_table_read"; size_t read_size = 0; size_t table_iterator = 0; ssize_t read_count = 0; uint32_t entry_hash = 0; uint32_t entry_offset = 0; uint32_t number_of_blocks = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint32_t value_32bit = 0; int number_of_items = 0; #endif if( hash_table == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid hash table.", function ); return( -1 ); } if( next_hash_table_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid next hash table offset.", function ); return( -1 ); } if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } if( block_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS, "%s: invalid block size value zero or less.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading HASH record at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, hash_table_offset, hash_table_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, hash_table_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek HASH record offset: %" PRIi64 ".", function, hash_table_offset ); return( -1 ); } read_count = libbfio_handle_read_buffer( file_io_handle, (uint8_t *) &hash_record_header, sizeof( msiecf_hash_record_header_t ), error ); if( read_count != (ssize_t) sizeof( msiecf_hash_record_header_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read HASH record header.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: HASH record header:\n", function ); libcnotify_print_data( (uint8_t *) &hash_record_header, sizeof( msiecf_hash_record_header_t ), 0 ); } #endif if( memory_compare( hash_record_header.signature, "HASH", 4 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported signature.", function ); return( -1 ); } byte_stream_copy_to_uint32_little_endian( hash_record_header.number_of_blocks, number_of_blocks ); byte_stream_copy_to_uint32_little_endian( hash_record_header.next_offset, *next_hash_table_offset ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: signature\t\t\t\t\t: %c%c%c%c\n", function, hash_record_header.signature[ 0 ], hash_record_header.signature[ 1 ], hash_record_header.signature[ 2 ], hash_record_header.signature[ 3 ] ); libcnotify_printf( "%s: number of blocks\t\t\t\t: %" PRIu32 "\n", function, number_of_blocks ); libcnotify_printf( "%s: next offset\t\t\t\t\t: %" PRIi64 " (0x%08" PRIx64 ")\n", function, *next_hash_table_offset, *next_hash_table_offset ); byte_stream_copy_to_uint32_little_endian( hash_record_header.sequence_number, value_32bit ); libcnotify_printf( "%s: sequence number\t\t\t\t: %" PRIu32 "\n", function, value_32bit ); libcnotify_printf( "\n" ); } #endif read_size = ( number_of_blocks * block_size ) - sizeof( msiecf_hash_record_header_t ); if( read_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid read size value exceeds maximum.", function ); return( -1 ); } if( ( read_size % 8 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported HASH record data size.", function ); return( -1 ); } hash_record_data = (uint8_t *) memory_allocate( read_size ); if( hash_record_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create HASH record data.", function ); return( -1 ); } read_count = libbfio_handle_read_buffer( file_io_handle, hash_record_data, read_size, error ); if( read_count != (ssize_t) read_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read HASH record data.", function ); memory_free( hash_record_data ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: HASH record data:\n", function ); libcnotify_print_data( hash_record_data, read_size, 0 ); } #endif read_size /= 8; entry_data = hash_record_data; for( table_iterator = 0; table_iterator < read_size; table_iterator++ ) { byte_stream_copy_to_uint32_little_endian( entry_data, entry_hash ); entry_data += 4; byte_stream_copy_to_uint32_little_endian( entry_data, entry_offset ); entry_data += 4; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: entry %03d hash\t\t\t\t: 0x%08" PRIx32 "\n", function, table_iterator, entry_hash ); libcnotify_printf( "%s: entry %03d offset\t\t\t\t: 0x%08" PRIx32 "\n", function, table_iterator, entry_offset ); } #endif /* Skip empty entries */ if( entry_hash == entry_offset ) { continue; } /* Skip uninitialized entries * These should only appear at the end of the HASH record data */ if( ( entry_hash == 0x0badf00d ) || ( entry_hash == 0xdeadbeef ) ) { continue; } /* Skip invalid URL entries */ if( ( entry_hash & 0x0f ) == 0x01 ) { continue; } /* Check if the entry record offset is block aligned */ if( ( entry_offset % block_size ) != 0 ) { continue; } #if defined( HAVE_DEBUG_OUTPUT ) number_of_items++; #endif /* TODO flag hashed items */ } memory_free( hash_record_data ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: found %d hashed items.\n", function, number_of_items ); libcnotify_printf( "\n" ); } #endif return( 1 ); }
/* Reads a record_values * Returns the number of bytes read if successful or -1 on error */ ssize_t libevt_record_values_read( libevt_record_values_t *record_values, libbfio_handle_t *file_io_handle, libevt_io_handle_t *io_handle, off64_t *file_offset, uint8_t strict_mode, libcerror_error_t **error ) { uint8_t record_size_data[ 4 ]; uint8_t *record_data = NULL; static char *function = "libevt_record_values_read"; size_t read_size = 0; size_t record_data_offset = 0; ssize_t read_count = 0; ssize_t total_read_count = 0; uint32_t record_data_size = 0; if( record_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid record values.", 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( file_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file offset.", function ); return( -1 ); } record_values->offset = *file_offset; read_count = libbfio_handle_read_buffer( file_io_handle, record_size_data, sizeof( uint32_t ), error ); if( read_count != (ssize_t) sizeof( uint32_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read record size data.", function ); goto on_error; } *file_offset += read_count; total_read_count = read_count; byte_stream_copy_to_uint32_little_endian( record_size_data, record_data_size ); if( record_data_size < 4 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: record data size value out of bounds.", function ); goto on_error; } #if SIZEOF_SIZE_T <= 4 if( (size_t) record_data_size > (size_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid record data size value exceeds maximum.", function ); goto on_error; } #endif /* Allocating record data as 4 bytes and then using realloc here * corrupts the memory */ record_data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * record_data_size ); if( record_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create record data.", function ); goto on_error; } byte_stream_copy_from_uint32_little_endian( record_data, record_data_size ); record_data_offset = 4; read_size = record_data_size - record_data_offset; if( ( (size64_t) *file_offset + read_size ) > io_handle->file_size ) { read_size = (size_t) ( io_handle->file_size - *file_offset ); } read_count = libbfio_handle_read_buffer( file_io_handle, &( record_data[ record_data_offset ] ), read_size, error ); if( read_count != (ssize_t) read_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read record data.", function ); goto on_error; } *file_offset += read_count; record_data_offset += read_count; total_read_count += read_count; if( record_data_offset < (size_t) record_data_size ) { if( libbfio_handle_seek_offset( file_io_handle, (off64_t) sizeof( evt_file_header_t ), SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek file header offset: %" PRIzd ".", function, sizeof( evt_file_header_t ) ); goto on_error; } *file_offset = (off64_t) sizeof( evt_file_header_t ); read_size = (size_t) record_data_size - record_data_offset; read_count = libbfio_handle_read_buffer( file_io_handle, &( record_data[ record_data_offset ] ), read_size, error ); if( read_count != (ssize_t) read_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read record data.", function ); goto on_error; } *file_offset += read_count; total_read_count += read_count; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: record data:\n", function ); libcnotify_print_data( record_data, (size_t) record_data_size, LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); } #endif if( memory_compare( &( record_data[ 4 ] ), evt_file_signature, 4 ) == 0 ) { record_values->type = LIBEVT_RECORD_TYPE_EVENT; } else if( memory_compare( &( record_data[ 4 ] ), evt_end_of_file_record_signature1, 4 ) == 0 ) { record_values->type = LIBEVT_RECORD_TYPE_END_OF_FILE; } else { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported record values signature.", function ); goto on_error; } if( record_values->type == LIBEVT_RECORD_TYPE_EVENT ) { if( libevt_record_values_read_event( record_values, record_data, (size_t) record_data_size, strict_mode, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read event record values.", function ); goto on_error; } } else if( record_values->type == LIBEVT_RECORD_TYPE_END_OF_FILE ) { if( libevt_record_values_read_end_of_file( record_values, record_data, (size_t) record_data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read end of file record values.", function ); goto on_error; } } memory_free( record_data ); return( total_read_count ); on_error: if( record_data != NULL ) { memory_free( record_data ); } return( -1 ); }
/* Reads the metadata area * Returns 1 if successful or -1 on error */ int libvslvm_metadata_area_read( libvslvm_metadata_area_t *metadata_area, libbfio_handle_t *file_io_handle, off64_t file_offset, libcerror_error_t **error ) { vslvm_raw_location_descriptor_t raw_location_descriptor_data; vslvm_metadata_area_header_t metadata_area_header; libvslvm_raw_location_descriptor_t *raw_location_descriptor = NULL; static char *function = "libvslvm_metadata_area_read"; ssize_t read_count = 0; uint64_t offset = 0; uint64_t size = 0; uint32_t checksum = 0; uint32_t flags = 0; int entry_index = 0; int result = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint64_t value_64bit = 0; uint32_t value_32bit = 0; #endif if( metadata_area == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid metadata area.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading metadata area at offset: %" PRIi64 "\n", function, file_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, file_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek offset: %" PRIi64 " (0x%08" PRIx64 ").", function, file_offset, file_offset ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, (uint8_t *) &metadata_area_header, sizeof( vslvm_metadata_area_header_t ), error ); if( read_count != (ssize_t) sizeof( vslvm_metadata_area_header_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read metadata area header.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: metadata area header data:\n", function ); libcnotify_print_data( (uint8_t *) &metadata_area_header, sizeof( vslvm_metadata_area_header_t ), 0 ); } #endif if( memory_compare( metadata_area_header.signature, vslvm_metadata_area_signature, 8 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported metadata area signature.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { byte_stream_copy_to_uint32_little_endian( metadata_area_header.checksum, value_32bit ); libcnotify_printf( "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: signature\t\t\t\t\t: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", function, metadata_area_header.signature[ 0 ], metadata_area_header.signature[ 1 ], metadata_area_header.signature[ 2 ], metadata_area_header.signature[ 3 ], metadata_area_header.signature[ 4 ], metadata_area_header.signature[ 5 ], metadata_area_header.signature[ 6 ], metadata_area_header.signature[ 7 ], metadata_area_header.signature[ 8 ], metadata_area_header.signature[ 9 ], metadata_area_header.signature[ 10 ], metadata_area_header.signature[ 11 ], metadata_area_header.signature[ 12 ], metadata_area_header.signature[ 13 ], metadata_area_header.signature[ 14 ], metadata_area_header.signature[ 15 ] ); byte_stream_copy_to_uint32_little_endian( metadata_area_header.version, value_32bit ); libcnotify_printf( "%s: version\t\t\t\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint64_little_endian( metadata_area_header.data_offset, value_64bit ); libcnotify_printf( "%s: data offset\t\t\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); byte_stream_copy_to_uint64_little_endian( metadata_area_header.data_size, value_64bit ); libcnotify_printf( "%s: data size\t\t\t\t\t: %" PRIu64 "\n", function, value_64bit ); libcnotify_printf( "\n" ); } #endif /* TODO calculate checksum */ do { read_count = libbfio_handle_read_buffer( file_io_handle, (uint8_t *) &raw_location_descriptor_data, sizeof( vslvm_raw_location_descriptor_t ), error ); if( read_count != (ssize_t) sizeof( vslvm_raw_location_descriptor_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read raw location descriptor.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: raw location descriptor data:\n", function ); libcnotify_print_data( (uint8_t *) &raw_location_descriptor_data, sizeof( vslvm_raw_location_descriptor_t ), 0 ); } #endif result = memory_compare( (uint8_t *) &raw_location_descriptor_data, vslvm_empty_raw_location_descriptor, sizeof( vslvm_raw_location_descriptor_t ) ); if( result != 0 ) { byte_stream_copy_to_uint64_little_endian( raw_location_descriptor_data.offset, offset ); byte_stream_copy_to_uint64_little_endian( raw_location_descriptor_data.size, size ); byte_stream_copy_to_uint32_little_endian( raw_location_descriptor_data.checksum, checksum ); byte_stream_copy_to_uint32_little_endian( raw_location_descriptor_data.flags, flags ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: offset\t\t\t\t\t: 0x%08" PRIx64 "\n", function, offset ); libcnotify_printf( "%s: size\t\t\t\t\t: %" PRIu64 "\n", function, size ); libcnotify_printf( "%s: checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", function, checksum ); libcnotify_printf( "%s: flags\t\t\t\t\t: 0x%08" PRIx32 "\n", function, flags ); libcnotify_printf( "\n" ); } #endif if( ( flags & LIBVSLVM_RAW_LOCATION_DESCRIPTOR_FLAG_IGNORE ) == 0 ) { if( libvslvm_raw_location_descriptor_initialize( &raw_location_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create raw location descriptor.", function ); goto on_error; } if( libvslvm_raw_location_descriptor_set( raw_location_descriptor, (off64_t) ( file_offset + offset ), (size64_t) size, checksum, flags, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set raw location descriptor.", function ); goto on_error; } if( libcdata_array_append_entry( metadata_area->raw_location_descriptors_array, &entry_index, (intptr_t *) raw_location_descriptor, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, "%s: unable to append entry to raw location descriptors array.", function ); goto on_error; } raw_location_descriptor = NULL; } } } while( result != 0 ); return( 1 ); on_error: if( raw_location_descriptor != NULL ) { libvslvm_raw_location_descriptor_free( &raw_location_descriptor, NULL ); } libcdata_array_empty( metadata_area->raw_location_descriptors_array, (int (*)(intptr_t **, libcerror_error_t **)) &libvslvm_raw_location_descriptor_free, NULL ); return( -1 ); }
/* Seeks an offset in a handle in the pool * Returns the offset if successful or -1 on error */ off64_t libbfio_pool_seek_offset( libbfio_pool_t *pool, int entry, off64_t offset, int whence, liberror_error_t **error ) { libbfio_internal_pool_t *internal_pool = NULL; static char *function = "libbfio_pool_seek_offset"; off64_t seek_offset = 0; int flags = 0; int is_open = 0; if( pool == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid pool.", function ); return( -1 ); } internal_pool = (libbfio_internal_pool_t *) pool; if( internal_pool->handles == NULL ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid pool - missing handles.", function ); return( -1 ); } if( ( entry < 0 ) || ( entry >= internal_pool->amount_of_handles ) ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_ARGUMENTS, LIBERROR_ARGUMENT_ERROR_VALUE_OUT_OF_RANGE, "%s: invalid entry.", function ); return( -1 ); } /* Make sure the handle is open */ is_open = libbfio_handle_is_open( internal_pool->handles[ entry ], error ); if( is_open == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to determine if entry: %d is open.", function, entry ); return( -1 ); } else if( is_open == 0 ) { if( libbfio_handle_get_flags( internal_pool->handles[ entry ], &flags, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_RUNTIME, LIBERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve flags.", function ); return( -1 ); } if( libbfio_pool_open_handle( internal_pool, internal_pool->handles[ entry ], flags, error ) != 1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open entry: %d.", function, entry ); return( -1 ); } } seek_offset = libbfio_handle_seek_offset( internal_pool->handles[ entry ], offset, whence, error ); if( seek_offset == -1 ) { liberror_error_set( error, LIBERROR_ERROR_DOMAIN_IO, LIBERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek offset in entry: %d.", function, entry ); return( -1 ); } return( seek_offset ); }
/* Reads a page and its values * Returns 1 if successful or -1 on error */ int libesedb_page_read( libesedb_page_t *page, libesedb_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, off64_t file_offset, libcerror_error_t **error ) { libcdata_array_t *page_tags_array = NULL; uint8_t *page_values_data = NULL; static char *function = "libesedb_page_read"; size_t page_values_data_offset = 0; size_t page_values_data_size = 0; ssize_t read_count = 0; uint32_t calculated_ecc32_checksum = 0; uint32_t calculated_page_number = 0; uint32_t calculated_xor32_checksum = 0; uint32_t stored_ecc32_checksum = 0; uint32_t stored_page_number = 0; uint32_t stored_xor32_checksum = 0; uint16_t available_data_size = 0; uint16_t available_page_tag = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint64_t value_64bit = 0; uint16_t value_16bit = 0; #endif if( page == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid page.", function ); return( -1 ); } if( page->data != NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, "%s: invalid page data already set.", 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 ); } calculated_page_number = (uint32_t) ( ( file_offset - io_handle->page_size ) / io_handle->page_size ); page->offset = file_offset; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading page: %" PRIu32 " at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, calculated_page_number, page->offset, page->offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, page->offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek page offset: %" PRIi64 ".", function, page->offset ); goto on_error; } page->data = (uint8_t *) memory_allocate( (size_t) io_handle->page_size ); if( page->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create page data.", function ); goto on_error; } page->data_size = (size_t) io_handle->page_size; read_count = libbfio_handle_read_buffer( file_io_handle, page->data, page->data_size, error ); if( read_count != (ssize_t) page->data_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read page data.", function ); goto on_error; } page_values_data = page->data; page_values_data_size = page->data_size; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: page header:\n", function ); libcnotify_print_data( page_values_data, sizeof( esedb_page_header_t ), 0 ); } #endif page->page_number = calculated_page_number; byte_stream_copy_to_uint16_little_endian( ( (esedb_page_header_t *) page_values_data )->available_data_size, available_data_size ); byte_stream_copy_to_uint32_little_endian( ( (esedb_page_header_t *) page_values_data )->previous_page, page->previous_page_number ); byte_stream_copy_to_uint32_little_endian( ( (esedb_page_header_t *) page_values_data )->next_page, page->next_page_number ); byte_stream_copy_to_uint32_little_endian( ( (esedb_page_header_t *) page_values_data )->father_data_page_object_identifier, page->father_data_page_object_identifier ); byte_stream_copy_to_uint16_little_endian( ( (esedb_page_header_t *) page_values_data )->available_page_tag, available_page_tag ); byte_stream_copy_to_uint32_little_endian( ( (esedb_page_header_t *) page_values_data )->page_flags, page->flags ); /* Make sure to read after the page flags */ if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER ) && ( io_handle->page_size >= 16384 ) ) { /* TODO handle checksum */ } else { byte_stream_copy_to_uint32_little_endian( ( (esedb_page_header_t *) page_values_data )->xor_checksum, stored_xor32_checksum ); if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_NEW_RECORD_FORMAT ) && ( ( page->flags & LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT ) != 0 ) ) { byte_stream_copy_to_uint32_little_endian( ( (esedb_page_header_t *) page_values_data )->ecc_checksum, stored_ecc32_checksum ); } else { byte_stream_copy_to_uint32_little_endian( ( (esedb_page_header_t *) page_values_data )->page_number, stored_page_number ); } } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: current page number\t\t\t\t\t: %" PRIu32 "\n", function, calculated_page_number ); if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER ) && ( io_handle->page_size >= 16384 ) ) { /* TODO handle checksum */ byte_stream_copy_to_uint64_little_endian( page_values_data, value_64bit ); libcnotify_printf( "%s: checksum\t\t\t\t\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); } else { libcnotify_printf( "%s: XOR checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", function, stored_xor32_checksum ); if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_NEW_RECORD_FORMAT ) && ( ( page->flags & LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT ) != 0 ) ) { libcnotify_printf( "%s: ECC checksum\t\t\t\t\t: 0x%08" PRIx32 "\n", function, stored_ecc32_checksum ); } else { libcnotify_printf( "%s: page number\t\t\t\t\t\t: %" PRIu32 "\n", function, stored_page_number ); } } libcnotify_printf( "%s: database modification time:\n", function ); libcnotify_print_data( ( (esedb_page_header_t *) page_values_data )->database_modification_time, 8, 0 ); libcnotify_printf( "%s: previous page number\t\t\t\t: %" PRIu32 "\n", function, page->previous_page_number ); libcnotify_printf( "%s: next page number\t\t\t\t\t: %" PRIu32 "\n", function, page->next_page_number ); libcnotify_printf( "%s: father data page (FDP) object identifier\t\t: %" PRIu32 "\n", function, page->father_data_page_object_identifier ); libcnotify_printf( "%s: available data size\t\t\t\t\t: %" PRIu32 "\n", function, available_data_size ); byte_stream_copy_to_uint16_little_endian( ( (esedb_page_header_t *) page_values_data )->available_uncommitted_data_size, value_16bit ); libcnotify_printf( "%s: available uncommitted data size\t\t\t: %" PRIu16 "\n", function, value_16bit ); byte_stream_copy_to_uint16_little_endian( ( (esedb_page_header_t *) page_values_data )->available_data_offset, value_16bit ); libcnotify_printf( "%s: available data offset\t\t\t\t: %" PRIu16 "\n", function, value_16bit ); libcnotify_printf( "%s: available page tag\t\t\t\t\t: %" PRIu32 "\n", function, available_page_tag ); libcnotify_printf( "%s: page flags\t\t\t\t\t\t: 0x%08" PRIx32 "\n", function, page->flags ); libesedb_debug_print_page_flags( page->flags ); libcnotify_printf( "\n" ); } #endif /* TODO for now don't bother calculating a checksum for uninitialized pages */ if( ( page_values_data[ 0 ] != 0 ) || ( page_values_data[ 1 ] != 0 ) || ( page_values_data[ 2 ] != 0 ) || ( page_values_data[ 3 ] != 0 ) ) { if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER ) && ( io_handle->page_size >= 16384 ) ) { /* TODO handle checksum */ } else if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_NEW_RECORD_FORMAT ) && ( ( page->flags & LIBESEDB_PAGE_FLAG_IS_NEW_RECORD_FORMAT ) != 0 ) ) { if( libesedb_checksum_calculate_little_endian_ecc32( &calculated_ecc32_checksum, &calculated_xor32_checksum, page_values_data, page_values_data_size, 8, calculated_page_number, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unable to calculate ECC-32 and XOR-32 checksum.", function ); goto on_error; } } else { if( libesedb_checksum_calculate_little_endian_xor32( &calculated_xor32_checksum, &( page_values_data[ 4 ] ), page_values_data_size - 4, 0x89abcdef, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unable to calculate XOR-32 checksum.", function ); goto on_error; } } if( stored_xor32_checksum != calculated_xor32_checksum ) { #ifdef TODO libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_INPUT, LIBCERROR_INPUT_ERROR_CRC_MISMATCH, "%s: mismatch in page XOR-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).", function, stored_xor32_checksum, calculated_xor32_checksum ); goto on_error; #else if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: mismatch in page XOR-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n", function, stored_xor32_checksum, calculated_xor32_checksum ); } #endif } if( stored_ecc32_checksum != calculated_ecc32_checksum ) { #ifdef TODO libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_INPUT, LIBCERROR_INPUT_ERROR_CRC_MISMATCH, "%s: mismatch in page ECC-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).", function, stored_ecc32_checksum, calculated_ecc32_checksum ); goto on_error; #else if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: mismatch in page ECC-32 checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n", function, stored_ecc32_checksum, calculated_ecc32_checksum ); } #endif } } page_values_data += sizeof( esedb_page_header_t ); page_values_data_size -= sizeof( esedb_page_header_t ); page_values_data_offset += sizeof( esedb_page_header_t ); if( ( io_handle->format_revision >= LIBESEDB_FORMAT_REVISION_EXTENDED_PAGE_HEADER ) && ( io_handle->page_size >= 16384 ) ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: extended page header:\n", function ); libcnotify_print_data( page_values_data, 40, 0 ); } #endif #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { byte_stream_copy_to_uint64_little_endian( ( (esedb_extended_page_header_t *) page_values_data )->checksum1, value_64bit ); libcnotify_printf( "%s: checksum1\t\t\t\t\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); byte_stream_copy_to_uint64_little_endian( ( (esedb_extended_page_header_t *) page_values_data )->checksum2, value_64bit ); libcnotify_printf( "%s: checksum2\t\t\t\t\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); byte_stream_copy_to_uint64_little_endian( ( (esedb_extended_page_header_t *) page_values_data )->checksum3, value_64bit ); libcnotify_printf( "%s: checksum3\t\t\t\t\t\t: 0x%08" PRIx64 "\n", function, value_64bit ); byte_stream_copy_to_uint64_little_endian( ( (esedb_extended_page_header_t *) page_values_data )->page_number, value_64bit ); libcnotify_printf( "%s: page number\t\t\t\t\t\t: %" PRIu64 "\n", function, value_64bit ); libcnotify_printf( "%s: unknown1:\n", function ); libcnotify_print_data( ( (esedb_extended_page_header_t *) page_values_data )->unknown1, 8, 0 ); } #endif page_values_data += sizeof( esedb_extended_page_header_t ); page_values_data_size -= sizeof( esedb_extended_page_header_t ); page_values_data_offset += sizeof( esedb_extended_page_header_t ); } if( available_page_tag > 0 ) { /* Create the page tags array */ if( libcdata_array_initialize( &page_tags_array, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create page tags array.", function ); goto on_error; } if( libesedb_page_read_tags( page_tags_array, io_handle, available_page_tag, page->data, page->data_size, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read page tags.", function ); goto on_error; } /* The offsets in the page tags are relative after the page header */ if( libesedb_page_read_values( page, io_handle, page_tags_array, page_values_data, page_values_data_size, page_values_data_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read page values.", function ); goto on_error; } if( libcdata_array_free( &page_tags_array, (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_tags_value_free, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free the page tags array.", function ); goto on_error; } } return( 1 ); on_error: if( page_tags_array != NULL ) { libcdata_array_free( &page_tags_array, (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_page_tags_value_free, NULL ); } if( page->data != NULL ) { memory_free( page->data ); page->data = NULL; } return( -1 ); }
/* Reads the file header * Returns 1 if successful or -1 on error */ int libevt_io_handle_read_file_header( libevt_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, uint32_t *first_record_offset, uint32_t *end_of_file_record_offset, libcerror_error_t **error ) { evt_file_header_t file_header; static char *function = "libevt_io_handle_read_file_header"; ssize_t read_count = 0; uint32_t size = 0; uint32_t size_copy = 0; #if defined( HAVE_DEBUG_OUTPUT ) uint32_t value_32bit = 0; #endif 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( first_record_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid first record offset.", function ); return( -1 ); } if( end_of_file_record_offset == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid end of file record offset.", function ); return( -1 ); } if( libbfio_handle_get_size( file_io_handle, &( io_handle->file_size ), error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to retrieve file size.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading file header at offset: 0 (0x00000000)\n", function ); } #endif if( libbfio_handle_seek_offset( file_io_handle, 0, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek file header offset: 0.", function ); return( -1 ); } read_count = libbfio_handle_read_buffer( file_io_handle, (uint8_t *) &file_header, sizeof( evt_file_header_t ), error ); if( read_count != (ssize_t) sizeof( evt_file_header_t ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read file header.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: file header:\n", function ); libcnotify_print_data( (uint8_t *) &file_header, sizeof( evt_file_header_t ), 0 ); } #endif if( memory_compare( file_header.signature, evt_file_signature, 4 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported file signature.", function ); return( -1 ); } byte_stream_copy_to_uint32_little_endian( file_header.size, size ); byte_stream_copy_to_uint32_little_endian( file_header.major_version, io_handle->major_version ); byte_stream_copy_to_uint32_little_endian( file_header.minor_version, io_handle->minor_version ); byte_stream_copy_to_uint32_little_endian( file_header.first_record_offset, *first_record_offset ); byte_stream_copy_to_uint32_little_endian( file_header.end_of_file_record_offset, *end_of_file_record_offset ); byte_stream_copy_to_uint32_little_endian( file_header.file_flags, io_handle->file_flags ); byte_stream_copy_to_uint32_little_endian( file_header.size_copy, size_copy ); #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: size\t\t\t\t\t: %" PRIu32 "\n", function, size ); libcnotify_printf( "%s: signature\t\t\t\t: %c%c%c%c\n", function, file_header.signature[ 0 ], file_header.signature[ 1 ], file_header.signature[ 2 ], file_header.signature[ 3 ] ); libcnotify_printf( "%s: major version\t\t\t: %" PRIu32 "\n", function, io_handle->major_version ); libcnotify_printf( "%s: minor version\t\t\t: %" PRIu32 "\n", function, io_handle->minor_version ); libcnotify_printf( "%s: first record offset\t\t\t: 0x%08" PRIx32 "\n", function, *first_record_offset ); libcnotify_printf( "%s: end of file record offset\t\t: 0x%08" PRIx32 "\n", function, *end_of_file_record_offset ); byte_stream_copy_to_uint32_little_endian( file_header.last_record_number, value_32bit ); libcnotify_printf( "%s: last record number\t\t\t: %" PRIu32 "\n", function, value_32bit ); byte_stream_copy_to_uint32_little_endian( file_header.first_record_number, value_32bit ); libcnotify_printf( "%s: first record number\t\t\t: %" PRIu32 "\n", function, value_32bit ); libcnotify_printf( "%s: file flags\t\t\t\t: 0x%08" PRIx32 "\n", function, io_handle->file_flags ); libevt_debug_print_file_flags( io_handle->file_flags ); libcnotify_printf( "\n" ); byte_stream_copy_to_uint32_little_endian( file_header.retention, value_32bit ); libcnotify_printf( "%s: retention\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); libcnotify_printf( "%s: size copy\t\t\t\t: %" PRIu32 "\n", function, size_copy ); libcnotify_printf( "\n" ); } #endif if( size != size_copy ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: value mismatch for size and copy ( %" PRIu32 " != %" PRIu32 " ).\n", function, size, size_copy ); } #endif /* If the size does not match the header size assume size copy contains * the correct value for the next validation check */ if( size != sizeof( evt_file_header_t ) ) { size = size_copy; } io_handle->flags |= LIBEVT_IO_HANDLE_FLAG_IS_CORRUPTED; } if( (size_t) size != sizeof( evt_file_header_t ) ) { #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: size: %" PRIu32 " does not match header size.\n", function, size ); } #endif io_handle->flags |= LIBEVT_IO_HANDLE_FLAG_IS_CORRUPTED; } return( 1 ); }
/* Determines if a file contains a BDE volume signature using a Basic File IO (bfio) handle * Returns 1 if true, 0 if not or -1 on error */ int libbde_check_volume_signature_file_io_handle( libbfio_handle_t *file_io_handle, libcerror_error_t **error ) { uint8_t signature[ 12 ]; static char *function = "libbde_check_volume_signature_file_io_handle"; ssize_t read_count = 0; int file_io_handle_is_open = 0; if( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } file_io_handle_is_open = libbfio_handle_is_open( file_io_handle, error ); if( file_io_handle_is_open == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open file.", function ); return( -1 ); } else if( file_io_handle_is_open == 0 ) { if( libbfio_handle_open( file_io_handle, LIBBFIO_OPEN_READ, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_OPEN_FAILED, "%s: unable to open file.", function ); return( -1 ); } } if( libbfio_handle_seek_offset( file_io_handle, 0, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek file header offset: 0.", function ); if( file_io_handle_is_open == 0 ) { libbfio_handle_close( file_io_handle, error ); } return( -1 ); } read_count = libbfio_handle_read_buffer( file_io_handle, signature, 12, error ); if( read_count != 12 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read signature.", function ); if( file_io_handle_is_open == 0 ) { libbfio_handle_close( file_io_handle, error ); } return( -1 ); } if( file_io_handle_is_open == 0 ) { if( libbfio_handle_close( file_io_handle, error ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_CLOSE_FAILED, "%s: unable to close file.", function ); return( -1 ); } } if( memory_compare( bde_signature, &( signature[ 3 ] ), 8 ) == 0 ) { return( 1 ); } return( 0 ); }
/* Reads the URL values from an URL record * Returns 1 if successful or -1 on error */ int libmsiecf_url_values_read( libmsiecf_url_values_t *url_values, libmsiecf_io_handle_t *io_handle, libbfio_handle_t *file_io_handle, off64_t url_record_offset, size32_t record_size, uint8_t item_flags, libcerror_error_t **error ) { uint8_t *url_record_data = NULL; static char *function = "libmsiecf_url_values_read"; ssize_t read_count = 0; ssize_t value_size = 0; uint32_t data_offset = 0; uint32_t data_size = 0; uint32_t filename_offset = 0; uint32_t location_offset = 0; uint32_t cache_entry_flags = 0; uint32_t unknown_offset = 0; uint16_t first_year = 0; uint16_t second_year = 0; uint8_t first_day_of_month = 0; uint8_t first_month = 0; uint8_t number_of_days = 0; uint8_t second_day_of_month = 0; uint8_t second_month = 0; #if defined( HAVE_DEBUG_OUTPUT ) system_character_t date_time_string[ 32 ]; libfdatetime_filetime_t *filetime = NULL; libfdatetime_fat_date_time_t *fat_date_time = NULL; uint8_t *visited_entry_data = NULL; size_t string_index = 0; uint32_t value_32bit = 0; uint16_t value_16bit = 0; int result = 0; int visited_entry_index = 0; #endif if( url_values == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid URL values.", 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( file_io_handle == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid file IO handle.", function ); return( -1 ); } if( record_size == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS, "%s: invalid record size value zero or less.", function ); return( -1 ); } #if SIZEOF_SIZE_T <= 4 if( record_size > (size32_t) SSIZE_MAX ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, "%s: invalid record size value exceeds maximum.", function ); return( -1 ); } #endif if( ( record_size % 8 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported URL record size.", function ); return( -1 ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: reading URL record at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", function, url_record_offset, url_record_offset ); } #endif if( libbfio_handle_seek_offset( file_io_handle, url_record_offset, SEEK_SET, error ) == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_SEEK_FAILED, "%s: unable to seek URL record offset: %" PRIi64 ".", function, url_record_offset ); goto on_error; } /* Add one block for tainted records */ if( ( item_flags & LIBMSIECF_ITEM_FLAG_TAINTED ) != 0 ) { record_size += LIBMSIECF_DEFAULT_BLOCK_SIZE; } url_record_data = (uint8_t *) memory_allocate( record_size ); if( url_record_data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create URL record data.", function ); goto on_error; } read_count = libbfio_handle_read_buffer( file_io_handle, url_record_data, record_size, error ); if( read_count != (ssize_t) record_size ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_IO, LIBCERROR_IO_ERROR_READ_FAILED, "%s: unable to read URL record data.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: URL record data:\n", function ); libcnotify_print_data( url_record_data, record_size, 0 ); } #endif if( memory_compare( url_record_data, "URL ", 4 ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported signature.", function ); goto on_error; } if( ( io_handle->major_version == 4 ) && ( io_handle->minor_version == 7 ) ) { byte_stream_copy_to_uint64_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->secondary_filetime, url_values->secondary_time ); byte_stream_copy_to_uint64_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->primary_filetime, url_values->primary_time ); byte_stream_copy_to_uint64_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->expiration_time, url_values->expiration_time ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->cached_file_size, url_values->cached_file_size ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->unknown_offset, unknown_offset ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->location_offset, location_offset ); url_values->cache_directory_index = ( (msiecf_url_record_header_v47_t *) url_record_data )->cache_directory_index; byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->filename_offset, filename_offset ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->data_offset, data_offset ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->data_size, data_size ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->last_checked_time, url_values->last_checked_time ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->number_of_hits, url_values->number_of_hits ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->cache_entry_flags, cache_entry_flags ); } else if( ( io_handle->major_version == 5 ) && ( io_handle->minor_version == 2 ) ) { byte_stream_copy_to_uint64_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->secondary_filetime, url_values->secondary_time ); byte_stream_copy_to_uint64_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->primary_filetime, url_values->primary_time ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->expiration_time, url_values->expiration_time ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->cached_file_size, url_values->cached_file_size ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->unknown_offset, unknown_offset ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->location_offset, location_offset ); url_values->cache_directory_index = ( (msiecf_url_record_header_v52_t *) url_record_data )->cache_directory_index; byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->filename_offset, filename_offset ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->data_offset, data_offset ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->data_size, data_size ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->last_checked_time, url_values->last_checked_time ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->number_of_hits, url_values->number_of_hits ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->cache_entry_flags, cache_entry_flags ); } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { if( libfdatetime_fat_date_time_initialize( &fat_date_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create FAT date time.", function ); goto on_error; } if( libfdatetime_filetime_initialize( &filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create filetime.", function ); goto on_error; } libcnotify_printf( "%s: signature\t\t\t\t\t: %c%c%c%c\n", function, url_record_data[ 0 ], url_record_data[ 1 ], url_record_data[ 2 ], url_record_data[ 3 ] ); byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->number_of_blocks, value_32bit ); libcnotify_printf( "%s: number of blocks\t\t\t\t: %" PRIu32 "\n", function, value_32bit ); if( libfdatetime_filetime_copy_from_byte_stream( filetime, ( (msiecf_url_record_header_v47_t *) url_record_data )->secondary_filetime, 8, LIBFDATETIME_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to copy filetime from byte stream.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfdatetime_filetime_copy_to_utf16_string( filetime, (uint16_t *) date_time_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ); #else result = libfdatetime_filetime_copy_to_utf8_string( filetime, (uint8_t *) date_time_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to copy filetime to date time string.", function ); goto on_error; } libcnotify_printf( "%s: secondary time\t\t\t\t: %" PRIs_SYSTEM "\n", function, date_time_string ); if( libfdatetime_filetime_copy_from_byte_stream( filetime, ( (msiecf_url_record_header_v47_t *) url_record_data )->primary_filetime, 8, LIBFDATETIME_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to copy filetime from byte stream.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfdatetime_filetime_copy_to_utf16_string( filetime, (uint16_t *) date_time_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ); #else result = libfdatetime_filetime_copy_to_utf8_string( filetime, (uint8_t *) date_time_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to copy filetime to date time string.", function ); goto on_error; } libcnotify_printf( "%s: primary time\t\t\t\t\t: %" PRIs_SYSTEM "\n", function, date_time_string ); if( ( io_handle->major_version == 4 ) && ( io_handle->minor_version == 7 ) ) { if( libfdatetime_filetime_copy_from_byte_stream( filetime, ( (msiecf_url_record_header_v47_t *) url_record_data )->expiration_time, 8, LIBFDATETIME_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to copy filetime from byte stream.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfdatetime_filetime_copy_to_utf16_string( filetime, (uint16_t *) date_time_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ); #else result = libfdatetime_filetime_copy_to_utf8_string( filetime, (uint8_t *) date_time_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to copy filetime to date time string.", function ); goto on_error; } } else if( ( io_handle->major_version == 5 ) && ( io_handle->minor_version == 2 ) ) { if( libfdatetime_fat_date_time_copy_from_byte_stream( fat_date_time, ( (msiecf_url_record_header_v52_t *) url_record_data )->expiration_time, 4, LIBFDATETIME_ENDIAN_LITTLE, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_GENERIC, "%s: unable to copy FAT date time from byte stream.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfdatetime_fat_date_time_copy_to_utf16_string( fat_date_time, (uint16_t *) date_time_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME, LIBFDATETIME_DATE_TIME_FORMAT_CTIME, error ); #else result = libfdatetime_fat_date_time_copy_to_utf8_string( fat_date_time, (uint8_t *) date_time_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_GENERIC, "%s: unable to copy FAT date time to date time string.", function ); goto on_error; } } libcnotify_printf( "%s: expiration time\t\t\t\t: %" PRIs_SYSTEM "\n", function, date_time_string ); if( ( io_handle->major_version == 5 ) && ( io_handle->minor_version == 2 ) ) { byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->unknown1, value_32bit ); libcnotify_printf( "%s: unknown1\t\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); } libcnotify_printf( "%s: cached file size\t\t\t\t: %" PRIu32 " bytes\n", function, url_values->cached_file_size ); if( ( io_handle->major_version == 4 ) && ( io_handle->minor_version == 7 ) ) { byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->unknown1, value_32bit ); libcnotify_printf( "%s: unknown1\t\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); } if( ( io_handle->major_version == 4 ) && ( io_handle->minor_version == 7 ) ) { byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->unknown3, value_32bit ); } else if( ( io_handle->major_version == 5 ) && ( io_handle->minor_version == 2 ) ) { byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->unknown3, value_32bit ); } libcnotify_printf( "%s: unknown3\t\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); if( ( io_handle->major_version == 4 ) && ( io_handle->minor_version == 7 ) ) { byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->unknown4, value_32bit ); } else if( ( io_handle->major_version == 5 ) && ( io_handle->minor_version == 2 ) ) { byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->unknown4, value_32bit ); } libcnotify_printf( "%s: unknown4\t\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); if( ( io_handle->major_version == 4 ) && ( io_handle->minor_version == 7 ) ) { byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->non_releasable_time_delta, value_32bit ); } else if( ( io_handle->major_version == 5 ) && ( io_handle->minor_version == 2 ) ) { byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->non_releasable_time_delta, value_32bit ); } libcnotify_printf( "%s: non-releasable time delta\t\t\t: %" PRIu32 " seconds\n", function, value_32bit ); libcnotify_printf( "%s: unknown offset\t\t\t\t: %" PRIu32 "\n", function, unknown_offset ); libcnotify_printf( "%s: location offset\t\t\t\t: %" PRIu32 "\n", function, location_offset ); libcnotify_printf( "%s: cache directory index\t\t\t: %" PRIu8 "\n", function, url_values->cache_directory_index ); if( ( io_handle->major_version == 4 ) && ( io_handle->minor_version == 7 ) ) { libcnotify_printf( "%s: unknown6\t\t\t\t\t: 0x%02" PRIx8 " 0x%02" PRIx8 " 0x%02" PRIx8 "\n", function, ( (msiecf_url_record_header_v47_t *) url_record_data )->unknown6[ 0 ], ( (msiecf_url_record_header_v47_t *) url_record_data )->unknown6[ 1 ], ( (msiecf_url_record_header_v47_t *) url_record_data )->unknown6[ 2 ] ); } else if( ( io_handle->major_version == 5 ) && ( io_handle->minor_version == 2 ) ) { libcnotify_printf( "%s: unknown6\t\t\t\t\t: 0x%02" PRIx8 " 0x%02" PRIx8 " 0x%02" PRIx8 "\n", function, ( (msiecf_url_record_header_v52_t *) url_record_data )->unknown6[ 0 ], ( (msiecf_url_record_header_v52_t *) url_record_data )->unknown6[ 1 ], ( (msiecf_url_record_header_v52_t *) url_record_data )->unknown6[ 2 ] ); } libcnotify_printf( "%s: filename offset\t\t\t\t: %" PRIu32 "\n", function, filename_offset ); libcnotify_printf( "%s: cache entry flags\t\t\t\t: 0x%08" PRIx32 "\n", function, cache_entry_flags ); libmsiecf_debug_print_cache_entry_flags( cache_entry_flags ); libcnotify_printf( "\n" ); libcnotify_printf( "%s: data offset\t\t\t\t\t: %" PRIu32 "\n", function, data_offset ); libcnotify_printf( "%s: data size\t\t\t\t\t: %" PRIu32 "\n", function, data_size ); if( ( io_handle->major_version == 4 ) && ( io_handle->minor_version == 7 ) ) { byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->unknown8, value_32bit ); } else if( ( io_handle->major_version == 5 ) && ( io_handle->minor_version == 2 ) ) { byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->unknown8, value_32bit ); } libcnotify_printf( "%s: unknown8\t\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); if( ( io_handle->major_version == 4 ) && ( io_handle->minor_version == 7 ) ) { result = libfdatetime_fat_date_time_copy_from_byte_stream( fat_date_time, ( (msiecf_url_record_header_v47_t *) url_record_data )->last_checked_time, 4, LIBFDATETIME_ENDIAN_LITTLE, error ); } else if( ( io_handle->major_version == 5 ) && ( io_handle->minor_version == 2 ) ) { result = libfdatetime_fat_date_time_copy_from_byte_stream( fat_date_time, ( (msiecf_url_record_header_v52_t *) url_record_data )->last_checked_time, 4, LIBFDATETIME_ENDIAN_LITTLE, error ); } if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_GENERIC, "%s: unable to copy FAT date time from byte stream.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfdatetime_fat_date_time_copy_to_utf16_string( fat_date_time, (uint16_t *) date_time_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME, error ); #else result = libfdatetime_fat_date_time_copy_to_utf8_string( fat_date_time, (uint8_t *) date_time_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_GENERIC, "%s: unable to copy FAT date time to date time string.", function ); goto on_error; } libcnotify_printf( "%s: last checked time\t\t\t\t: %" PRIs_SYSTEM "\n", function, date_time_string ); libcnotify_printf( "%s: number of hits\t\t\t\t: %" PRIu32 "\n", function, url_values->number_of_hits ); if( ( io_handle->major_version == 4 ) && ( io_handle->minor_version == 7 ) ) { byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v47_t *) url_record_data )->unknown9, value_32bit ); } else if( ( io_handle->major_version == 5 ) && ( io_handle->minor_version == 2 ) ) { byte_stream_copy_to_uint32_little_endian( ( (msiecf_url_record_header_v52_t *) url_record_data )->unknown9, value_32bit ); } libcnotify_printf( "%s: unknown9\t\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); if( ( io_handle->major_version == 4 ) && ( io_handle->minor_version == 7 ) ) { result = libfdatetime_fat_date_time_copy_from_byte_stream( fat_date_time, ( (msiecf_url_record_header_v47_t *) url_record_data )->unknown_time, 4, LIBFDATETIME_ENDIAN_LITTLE, error ); } else if( ( io_handle->major_version == 5 ) && ( io_handle->minor_version == 2 ) ) { result = libfdatetime_fat_date_time_copy_from_byte_stream( fat_date_time, ( (msiecf_url_record_header_v52_t *) url_record_data )->unknown_time, 4, LIBFDATETIME_ENDIAN_LITTLE, error ); } if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_GENERIC, "%s: unable to copy FAT date time from byte stream.", function ); goto on_error; } #if defined( HAVE_WIDE_SYSTEM_CHARACTER ) result = libfdatetime_fat_date_time_copy_to_utf16_string( fat_date_time, (uint16_t *) date_time_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME, error ); #else result = libfdatetime_fat_date_time_copy_to_utf8_string( fat_date_time, (uint8_t *) date_time_string, 32, LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME, error ); #endif if( result != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_CONVERSION, LIBCERROR_CONVERSION_ERROR_GENERIC, "%s: unable to create FAT date time string.", function ); goto on_error; } libcnotify_printf( "%s: unknown time\t\t\t\t\t: %" PRIs_SYSTEM "\n", function, date_time_string ); if( libfdatetime_filetime_free( &filetime, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free filetime.", function ); goto on_error; } if( libfdatetime_fat_date_time_free( &fat_date_time, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, "%s: unable to free FAT date time.", function ); goto on_error; } } #endif if( unknown_offset > 0 ) { if( unknown_offset > record_size ) { if( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: unknown offset exceeds URL record data.", function ); goto on_error; } else { memory_free( url_record_data ); return( 1 ); } } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: unknown:\n", function ); libcnotify_print_data( &( url_record_data[ unknown_offset ] ), 8, 0 ); } #endif } if( location_offset > 0 ) { if( location_offset > record_size ) { if( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: location offset exceeds size of URL record data.", function ); return( -1 ); } } else { if( libfvalue_value_type_initialize( &( url_values->location ), LIBFVALUE_VALUE_TYPE_STRING_BYTE_STREAM, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create location value.", function ); goto on_error; } value_size = libfvalue_value_type_set_data_string( url_values->location, &( url_record_data[ location_offset ] ), record_size - location_offset, io_handle->ascii_codepage, LIBFVALUE_VALUE_DATA_FLAG_MANAGED, error ); if( value_size == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set data of location value.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: location\t\t\t\t\t: ", function ); if( libfvalue_value_print( url_values->location, 0, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print location value.", function ); goto on_error; } libcnotify_printf( "\n" ); if( libmsiecf_hash_calculate( &value_32bit, &( url_record_data[ location_offset ] ), record_size - location_offset, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to calculate location hash.", function ); goto on_error; } libcnotify_printf( "%s: hash value\t\t\t\t\t: 0x%08" PRIx32 "\n", function, value_32bit ); } #endif if( ( url_record_data[ location_offset + value_size - 1 ] != 0 ) && ( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported unterminated location string.", function ); goto on_error; } if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_UNDEFINED ) { if( value_size >= 18 ) { if( ( url_record_data[ location_offset ] == (uint8_t) ':' ) && ( url_record_data[ location_offset + 1 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 1 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 2 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 2 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 3 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 3 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 4 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 4 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 5 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 5 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 6 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 6 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 7 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 7 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 8 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 8 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 9 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 9 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 10 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 10 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 11 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 11 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 12 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 12 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 13 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 13 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 14 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 14 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 15 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 15 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 16 ] >= (uint8_t) '0' ) && ( url_record_data[ location_offset + 16 ] <= (uint8_t) '9' ) && ( url_record_data[ location_offset + 17 ] == (uint8_t) ':' ) ) { first_year = (uint16_t) url_record_data[ location_offset + 1 ] - (uint8_t) '0'; first_year *= 10; first_year += (uint16_t) url_record_data[ location_offset + 2 ] - (uint8_t) '0'; first_year *= 10; first_year += (uint16_t) url_record_data[ location_offset + 3 ] - (uint8_t) '0'; first_year *= 10; first_year += (uint16_t) url_record_data[ location_offset + 4 ] - (uint8_t) '0'; first_month = url_record_data[ location_offset + 5 ] - (uint8_t) '0'; first_month *= 10; first_month += url_record_data[ location_offset + 6 ] - (uint8_t) '0'; first_day_of_month = url_record_data[ location_offset + 7 ] - (uint8_t) '0'; first_day_of_month *= 10; first_day_of_month += url_record_data[ location_offset + 8 ] - (uint8_t) '0'; second_year = (uint16_t) url_record_data[ location_offset + 9 ] - (uint8_t) '0'; second_year *= 10; second_year += (uint16_t) url_record_data[ location_offset + 10 ] - (uint8_t) '0'; second_year *= 10; second_year += (uint16_t) url_record_data[ location_offset + 11 ] - (uint8_t) '0'; second_year *= 10; second_year += (uint16_t) url_record_data[ location_offset + 12 ] - (uint8_t) '0'; second_month = url_record_data[ location_offset + 13 ] - (uint8_t) '0'; second_month *= 10; second_month += url_record_data[ location_offset + 14 ] - (uint8_t) '0'; second_day_of_month = url_record_data[ location_offset + 15 ] - (uint8_t) '0'; second_day_of_month *= 10; second_day_of_month += url_record_data[ location_offset + 16 ] - (uint8_t) '0'; number_of_days = 0; if( first_year == second_year ) { if( first_month == second_month ) { if( first_day_of_month < second_day_of_month ) { number_of_days = second_day_of_month - first_day_of_month; } } else if( ( first_month + 1 ) == second_month ) { switch( first_month ) { case 3: case 5: case 7: case 8: case 10: case 12: number_of_days = ( 31 + second_day_of_month ) - first_day_of_month; break; case 2: if( ( ( ( first_year % 4 ) == 0 ) && ( ( first_year % 100 ) != 0 ) ) || ( ( first_year % 400 ) == 0 ) ) { number_of_days = ( 29 + second_day_of_month ) - first_day_of_month; } else { number_of_days = ( 28 + second_day_of_month ) - first_day_of_month; } break; case 4: case 6: case 9: case 11: number_of_days = ( 30 + second_day_of_month ) - first_day_of_month; break; } } } else if( ( first_year + 1 ) == second_year ) { if( ( first_month == 12 ) && ( second_month == 1 ) ) { number_of_days = ( 31 + second_day_of_month ) - first_day_of_month; } } if( number_of_days == 1 ) { url_values->type = LIBMSIECF_URL_ITEM_TYPE_HISTORY_DAILY; } else if( number_of_days == 7 ) { url_values->type = LIBMSIECF_URL_ITEM_TYPE_HISTORY_WEEKLY; } } } } if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_UNDEFINED ) { if( value_size >= 11 ) { if( memory_compare( &( url_record_data[ location_offset ] ), "iedownload:", 11 ) == 0 ) { url_values->type = LIBMSIECF_URL_ITEM_TYPE_DOWNLOAD; } } } if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_UNDEFINED ) { if( value_size >= 9 ) { if( memory_compare( &( url_record_data[ location_offset ] ), "DOMStore:", 9 ) == 0 ) { url_values->type = LIBMSIECF_URL_ITEM_TYPE_DOM_STORE; } else if( memory_compare( &( url_record_data[ location_offset ] ), "feedplat:", 9 ) == 0 ) { url_values->type = LIBMSIECF_URL_ITEM_TYPE_RSS_FEED; } else if( memory_compare( &( url_record_data[ location_offset ] ), "iecompat:", 9 ) == 0 ) { url_values->type = LIBMSIECF_URL_ITEM_TYPE_COMPATIBILITY; } else if( memory_compare( &( url_record_data[ location_offset ] ), "PrivacIE:", 9 ) == 0 ) { url_values->type = LIBMSIECF_URL_ITEM_TYPE_INPRIVATE_FILTERING; } else if( memory_compare( &( url_record_data[ location_offset ] ), "userdata:", 9 ) == 0 ) { url_values->type = LIBMSIECF_URL_ITEM_TYPE_USER_DATA; } } } if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_UNDEFINED ) { if( value_size >= 8 ) { if( memory_compare( &( url_record_data[ location_offset ] ), "Visited:", 8 ) == 0 ) { url_values->type = LIBMSIECF_URL_ITEM_TYPE_HISTORY; } } } if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_UNDEFINED ) { if( value_size >= 7 ) { if( memory_compare( &( url_record_data[ location_offset ] ), "Cookie:", 7 ) == 0 ) { url_values->type = LIBMSIECF_URL_ITEM_TYPE_COOKIE; } } } if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_UNDEFINED ) { if( value_size >= 6 ) { if( memory_compare( &( url_record_data[ location_offset ] ), "ietld:", 6 ) == 0 ) { url_values->type = LIBMSIECF_URL_ITEM_TYPE_TLD; } } } if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_UNDEFINED ) { url_values->type = LIBMSIECF_URL_ITEM_TYPE_CACHE; /* TODO way to determine unknown url_values->type = LIBMSIECF_URL_ITEM_TYPE_UNKNOWN; */ } } } if( filename_offset > 0 ) { if( filename_offset > record_size ) { if( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: filename offset exceeds size of URL record data.", function ); goto on_error; } } else { if( libfvalue_value_type_initialize( &( url_values->filename ), LIBFVALUE_VALUE_TYPE_STRING_BYTE_STREAM, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, "%s: unable to create filename value.", function ); goto on_error; } value_size = libfvalue_value_type_set_data_string( url_values->filename, &( url_record_data[ filename_offset ] ), record_size - filename_offset, io_handle->ascii_codepage, LIBFVALUE_VALUE_DATA_FLAG_MANAGED, error ); if( value_size == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to set data of filename value.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: filename\t\t\t\t\t: ", function ); if( libfvalue_value_print( url_values->filename, 0, 0, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, "%s: unable to print filename value.", function ); goto on_error; } libcnotify_printf( "\n" ); } #endif if( ( url_record_data[ filename_offset + value_size - 1 ] != 0 ) && ( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, "%s: unsupported unterminated filename string.", function ); goto on_error; } } } if( data_offset > 0 ) { if( data_offset > record_size ) { if( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: data offset exceeds size of URL record data.", function ); goto on_error; } } else { if( ( data_offset + data_size ) > record_size ) { if( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, "%s: data size exceeds size of URL record data.", function ); goto on_error; } else { data_size = record_size - data_offset; } } url_values->data_size = (size_t) data_size; url_values->data = (uint8_t *) memory_allocate( sizeof( uint8_t ) * url_values->data_size ); if( url_values->data == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to create data.", function ); goto on_error; } if( memory_copy( url_values->data, &( url_record_data[ data_offset ] ), url_values->data_size ) == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_MEMORY, LIBCERROR_MEMORY_ERROR_INSUFFICIENT, "%s: unable to copy data.", function ); goto on_error; } #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "%s: data:\n", function ); libcnotify_print_data( &( url_record_data[ data_offset ] ), data_size, 0 ); if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_CACHE ) { /* The data string in not necessarily terminated by an end-of-string character */ libcnotify_printf( "%s: data string\t\t\t\t\t: ", function ); for( string_index = 0; string_index < data_size; string_index++ ) { libcnotify_printf( "%c", url_record_data[ data_offset + string_index ] ); } libcnotify_printf( "\n" ); } else if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_HISTORY ) { visited_entry_data = &( url_record_data[ data_offset ] ); do { visited_entry_index++; byte_stream_copy_to_uint16_little_endian( visited_entry_data, value_16bit ); visited_entry_data += 2; libcnotify_printf( "%s: data entry: %02d size\t\t\t\t: %" PRIu16 "\n", function, visited_entry_index, value_16bit ); libcnotify_printf( "%s: data entry: %02d type\t\t\t\t: 0x%02" PRIx8 " (%s : %s)\n", function, visited_entry_index, visited_entry_data[ 0 ], libmsiecf_property_type_get_identifier( NULL, (uint32_t) visited_entry_data[ 0 ], (uint32_t) visited_entry_data[ 1 ] ), libmsiecf_property_type_get_description( NULL, (uint32_t) visited_entry_data[ 0 ], (uint32_t) visited_entry_data[ 1 ] ) ); libcnotify_printf( "%s: data entry: %02d value type\t\t\t: 0x%02" PRIx8 " (%s : %s)\n", function, visited_entry_index, visited_entry_data[ 1 ], libfole_value_type_get_identifier( (uint32_t) visited_entry_data[ 1 ] ), libfole_value_type_get_description( (uint32_t) visited_entry_data[ 1 ] ) ); visited_entry_data += 2; if( value_16bit > 4 ) { value_16bit -= 4; libcnotify_printf( "%s: data entry: %02d value:\n", function, visited_entry_index ); libcnotify_print_data( visited_entry_data, value_16bit, 0 ); visited_entry_data += value_16bit; } } while( value_16bit > 0 ); } } #endif } } memory_free( url_record_data ); url_record_data = NULL; #if defined( HAVE_DEBUG_OUTPUT ) if( libcnotify_verbose != 0 ) { libcnotify_printf( "\n" ); } #endif #if defined( HAVE_VERBOSE_OUTPUT ) switch( url_values->type ) { case LIBMSIECF_URL_ITEM_TYPE_COOKIE: if ( ( cache_entry_flags & LIBMSIECF_CACHE_ENTRY_FLAG_COOKIE ) == 0 ) { libcnotify_printf( "%s: detected type cookie but corresponding cache entry flag (COOKIE_CACHE_ENTRY) is not set.\n", function ); } break; case LIBMSIECF_URL_ITEM_TYPE_HISTORY: if ( ( cache_entry_flags & LIBMSIECF_CACHE_ENTRY_FLAG_URLHISTORY ) == 0 ) { libcnotify_printf( "%s: detected type history but corresponding cache entry flag (URLHISTORY_CACHE_ENTRY) is not set.\n", function ); } break; case LIBMSIECF_URL_ITEM_TYPE_HISTORY_DAILY: case LIBMSIECF_URL_ITEM_TYPE_HISTORY_WEEKLY: if ( ( cache_entry_flags & LIBMSIECF_CACHE_ENTRY_FLAG_URLHISTORY ) == 0 ) { libcnotify_printf( "%s: detected type history periodic but corresponding cache entry flag (URLHISTORY_CACHE_ENTRY) is not set.\n", function ); } break; } #endif return( 1 ); on_error: #if defined( HAVE_DEBUG_OUTPUT ) if( filetime != NULL ) { libfdatetime_filetime_free( &filetime, NULL ); } if( fat_date_time != NULL ) { libfdatetime_fat_date_time_free( &fat_date_time, NULL ); } #endif if( url_record_data != NULL ) { memory_free( url_record_data ); } return( -1 ); }