1 /*
2  * File functions
3  *
4  * Copyright (C) 2009-2021, Joachim Metz <joachim.metz@gmail.com>
5  *
6  * Refer to AUTHORS for acknowledgements.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <common.h>
23 #include <memory.h>
24 #include <narrow_string.h>
25 #include <types.h>
26 #include <wide_string.h>
27 
28 #include "libesedb_catalog.h"
29 #include "libesedb_database.h"
30 #include "libesedb_debug.h"
31 #include "libesedb_definitions.h"
32 #include "libesedb_i18n.h"
33 #include "libesedb_io_handle.h"
34 #include "libesedb_file.h"
35 #include "libesedb_file_header.h"
36 #include "libesedb_libbfio.h"
37 #include "libesedb_libcerror.h"
38 #include "libesedb_libcnotify.h"
39 #include "libesedb_libfcache.h"
40 #include "libesedb_libfdata.h"
41 #include "libesedb_page.h"
42 #include "libesedb_table.h"
43 #include "libesedb_table_definition.h"
44 
45 /* Creates a file
46  * Make sure the value file is referencing, is set to NULL
47  * Returns 1 if successful or -1 on error
48  */
libesedb_file_initialize(libesedb_file_t ** file,libcerror_error_t ** error)49 int libesedb_file_initialize(
50      libesedb_file_t **file,
51      libcerror_error_t **error )
52 {
53 	libesedb_internal_file_t *internal_file = NULL;
54 	static char *function                   = "libesedb_file_initialize";
55 
56 	if( file == NULL )
57 	{
58 		libcerror_error_set(
59 		 error,
60 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
61 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
62 		 "%s: invalid file.",
63 		 function );
64 
65 		return( -1 );
66 	}
67 	if( *file != NULL )
68 	{
69 		libcerror_error_set(
70 		 error,
71 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
72 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
73 		 "%s: invalid file value already set.",
74 		 function );
75 
76 		return( -1 );
77 	}
78 	internal_file = memory_allocate_structure(
79 	                 libesedb_internal_file_t );
80 
81 	if( internal_file == NULL )
82 	{
83 		libcerror_error_set(
84 		 error,
85 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
86 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
87 		 "%s: unable to create file.",
88 		 function );
89 
90 		goto on_error;
91 	}
92 	if( memory_set(
93 	     internal_file,
94 	     0,
95 	     sizeof( libesedb_internal_file_t ) ) == NULL )
96 	{
97 		libcerror_error_set(
98 		 error,
99 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
100 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
101 		 "%s: unable to clear file.",
102 		 function );
103 
104 		memory_free(
105 		 internal_file );
106 
107 		return( -1 );
108 	}
109 	if( libesedb_io_handle_initialize(
110 	     &( internal_file->io_handle ),
111 	     error ) != 1 )
112 	{
113 		libcerror_error_set(
114 		 error,
115 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
116 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
117 		 "%s: unable to create IO handle.",
118 		 function );
119 
120 		goto on_error;
121 	}
122 	if( libesedb_i18n_initialize(
123 	     error ) != 1 )
124 	{
125 		libcerror_error_set(
126 		 error,
127 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
128 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
129 		 "%s: unable to initalize internationalization (i18n).",
130 		 function );
131 
132 		goto on_error;
133 	}
134 	*file = (libesedb_file_t *) internal_file;
135 
136 	return( 1 );
137 
138 on_error:
139 	if( internal_file != NULL )
140 	{
141 		if( internal_file->io_handle != NULL )
142 		{
143 			libesedb_io_handle_free(
144 			 &( internal_file->io_handle ),
145 			 NULL );
146 		}
147 		memory_free(
148 		 internal_file );
149 	}
150 	return( -1 );
151 }
152 
153 /* Frees a file
154  * Returns 1 if successful or -1 on error
155  */
libesedb_file_free(libesedb_file_t ** file,libcerror_error_t ** error)156 int libesedb_file_free(
157      libesedb_file_t **file,
158      libcerror_error_t **error )
159 {
160 	libesedb_internal_file_t *internal_file = NULL;
161 	static char *function                   = "libesedb_file_free";
162 	int result                              = 1;
163 
164 	if( file == NULL )
165 	{
166 		libcerror_error_set(
167 		 error,
168 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
169 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
170 		 "%s: invalid file.",
171 		 function );
172 
173 		return( -1 );
174 	}
175 	if( *file != NULL )
176 	{
177 		internal_file = (libesedb_internal_file_t *) *file;
178 
179 		if( internal_file->file_io_handle != NULL )
180 		{
181 			if( libesedb_file_close(
182 			     *file,
183 			     error ) != 0 )
184 			{
185 				libcerror_error_set(
186 				 error,
187 				 LIBCERROR_ERROR_DOMAIN_IO,
188 				 LIBCERROR_IO_ERROR_CLOSE_FAILED,
189 				 "%s: unable to close file.",
190 				 function );
191 
192 				result = -1;
193 			}
194 		}
195 		*file = NULL;
196 
197 		if( libesedb_io_handle_free(
198 		     &( internal_file->io_handle ),
199 		     error ) != 1 )
200 		{
201 			libcerror_error_set(
202 			 error,
203 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
204 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
205 			 "%s: unable to free IO handle.",
206 			 function );
207 
208 			result = -1;
209 		}
210 		memory_free(
211 		 internal_file );
212 	}
213 	return( result );
214 }
215 
216 /* Signals a file to abort its current activity
217  * Returns 1 if successful or -1 on error
218  */
libesedb_file_signal_abort(libesedb_file_t * file,libcerror_error_t ** error)219 int libesedb_file_signal_abort(
220      libesedb_file_t *file,
221      libcerror_error_t **error )
222 {
223 	libesedb_internal_file_t *internal_file = NULL;
224 	static char *function                   = "libesedb_file_signal_abort";
225 
226 	if( file == NULL )
227 	{
228 		libcerror_error_set(
229 		 error,
230 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
231 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
232 		 "%s: invalid file.",
233 		 function );
234 
235 		return( -1 );
236 	}
237 	internal_file = (libesedb_internal_file_t *) file;
238 
239 	if( internal_file->io_handle == NULL )
240 	{
241 		libcerror_error_set(
242 		 error,
243 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
244 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
245 		 "%s: invalid file - missing IO handle.",
246 		 function );
247 
248 		return( -1 );
249 	}
250 	internal_file->io_handle->abort = 1;
251 
252 	return( 1 );
253 }
254 
255 /* Opens a file
256  * Returns 1 if successful or -1 on error
257  */
libesedb_file_open(libesedb_file_t * file,const char * filename,int access_flags,libcerror_error_t ** error)258 int libesedb_file_open(
259      libesedb_file_t *file,
260      const char *filename,
261      int access_flags,
262      libcerror_error_t **error )
263 {
264 	libbfio_handle_t *file_io_handle        = NULL;
265 	libesedb_internal_file_t *internal_file = NULL;
266 	static char *function                   = "libesedb_file_open";
267 	size_t filename_length                  = 0;
268 
269 	if( file == NULL )
270 	{
271 		libcerror_error_set(
272 		 error,
273 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
274 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
275 		 "%s: invalid file.",
276 		 function );
277 
278 		return( -1 );
279 	}
280 	internal_file = (libesedb_internal_file_t *) file;
281 
282 	if( filename == NULL )
283 	{
284 		libcerror_error_set(
285 		 error,
286 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
287 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
288 		 "%s: invalid filename.",
289 		 function );
290 
291 		return( -1 );
292 	}
293 	if( ( ( access_flags & LIBESEDB_ACCESS_FLAG_READ ) == 0 )
294 	 && ( ( access_flags & LIBESEDB_ACCESS_FLAG_WRITE ) == 0 ) )
295 	{
296 		libcerror_error_set(
297 		 error,
298 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
299 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
300 		 "%s: unsupported access flags.",
301 		 function );
302 
303 		return( -1 );
304 	}
305 	if( ( access_flags & LIBESEDB_ACCESS_FLAG_WRITE ) != 0 )
306 	{
307 		libcerror_error_set(
308 		 error,
309 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
310 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
311 		 "%s: write access currently not supported.",
312 		 function );
313 
314 		return( -1 );
315 	}
316 	if( libbfio_file_initialize(
317 	     &file_io_handle,
318 	     error ) != 1 )
319 	{
320 		libcerror_error_set(
321 		 error,
322 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
323 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
324 		 "%s: unable to create file IO handle.",
325 		 function );
326 
327 		goto on_error;
328 	}
329 #if defined( HAVE_DEBUG_OUTPUT )
330 	if( libbfio_handle_set_track_offsets_read(
331 	     file_io_handle,
332 	     1,
333 	     error ) != 1 )
334 	{
335                 libcerror_error_set(
336                  error,
337                  LIBCERROR_ERROR_DOMAIN_RUNTIME,
338                  LIBCERROR_RUNTIME_ERROR_SET_FAILED,
339                  "%s: unable to set track offsets read in file IO handle.",
340                  function );
341 
342 		goto on_error;
343 	}
344 #endif
345 	filename_length = narrow_string_length(
346 	                   filename );
347 
348 	if( libbfio_file_set_name(
349 	     file_io_handle,
350 	     filename,
351 	     filename_length + 1,
352 	     error ) != 1 )
353 	{
354                 libcerror_error_set(
355                  error,
356                  LIBCERROR_ERROR_DOMAIN_RUNTIME,
357                  LIBCERROR_RUNTIME_ERROR_SET_FAILED,
358                  "%s: unable to set filename in file IO handle.",
359                  function );
360 
361 		goto on_error;
362 	}
363 	if( libesedb_file_open_file_io_handle(
364 	     file,
365 	     file_io_handle,
366 	     access_flags,
367 	     error ) != 1 )
368 	{
369 		libcerror_error_set(
370 		 error,
371 		 LIBCERROR_ERROR_DOMAIN_IO,
372 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
373 		 "%s: unable to open file: %s.",
374 		 function,
375 		 filename );
376 
377 		goto on_error;
378 	}
379 	internal_file->file_io_handle_created_in_library = 1;
380 
381 	return( 1 );
382 
383 on_error:
384 	if( file_io_handle != NULL )
385 	{
386 		libbfio_handle_free(
387 		 &file_io_handle,
388 		 NULL );
389 	}
390 	return( -1 );
391 }
392 
393 #if defined( HAVE_WIDE_CHARACTER_TYPE )
394 
395 /* Opens a file
396  * Returns 1 if successful or -1 on error
397  */
libesedb_file_open_wide(libesedb_file_t * file,const wchar_t * filename,int access_flags,libcerror_error_t ** error)398 int libesedb_file_open_wide(
399      libesedb_file_t *file,
400      const wchar_t *filename,
401      int access_flags,
402      libcerror_error_t **error )
403 {
404 	libbfio_handle_t *file_io_handle        = NULL;
405 	libesedb_internal_file_t *internal_file = NULL;
406 	static char *function                   = "libesedb_file_open_wide";
407 	size_t filename_length                  = 0;
408 
409 	if( file == NULL )
410 	{
411 		libcerror_error_set(
412 		 error,
413 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
414 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
415 		 "%s: invalid file.",
416 		 function );
417 
418 		return( -1 );
419 	}
420 	internal_file = (libesedb_internal_file_t *) file;
421 
422 	if( filename == NULL )
423 	{
424 		libcerror_error_set(
425 		 error,
426 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
427 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
428 		 "%s: invalid filename.",
429 		 function );
430 
431 		return( -1 );
432 	}
433 	if( ( ( access_flags & LIBESEDB_ACCESS_FLAG_READ ) == 0 )
434 	 && ( ( access_flags & LIBESEDB_ACCESS_FLAG_WRITE ) == 0 ) )
435 	{
436 		libcerror_error_set(
437 		 error,
438 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
439 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
440 		 "%s: unsupported access flags.",
441 		 function );
442 
443 		return( -1 );
444 	}
445 	if( ( access_flags & LIBESEDB_ACCESS_FLAG_WRITE ) != 0 )
446 	{
447 		libcerror_error_set(
448 		 error,
449 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
450 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
451 		 "%s: write access currently not supported.",
452 		 function );
453 
454 		return( -1 );
455 	}
456 	if( libbfio_file_initialize(
457 	     &file_io_handle,
458 	     error ) != 1 )
459 	{
460 		libcerror_error_set(
461 		 error,
462 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
463 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
464 		 "%s: unable to create file IO handle.",
465 		 function );
466 
467 		goto on_error;
468 	}
469 #if defined( HAVE_DEBUG_OUTPUT )
470 	if( libbfio_handle_set_track_offsets_read(
471 	     file_io_handle,
472 	     1,
473 	     error ) != 1 )
474 	{
475                 libcerror_error_set(
476                  error,
477                  LIBCERROR_ERROR_DOMAIN_RUNTIME,
478                  LIBCERROR_RUNTIME_ERROR_SET_FAILED,
479                  "%s: unable to set track offsets read in file IO handle.",
480                  function );
481 
482 		goto on_error;
483 	}
484 #endif
485 	filename_length = wide_string_length(
486 	                   filename );
487 
488 	if( libbfio_file_set_name_wide(
489 	     file_io_handle,
490 	     filename,
491 	     filename_length + 1,
492 	     error ) != 1 )
493 	{
494                 libcerror_error_set(
495                  error,
496                  LIBCERROR_ERROR_DOMAIN_RUNTIME,
497                  LIBCERROR_RUNTIME_ERROR_SET_FAILED,
498                  "%s: unable to set filename in file IO handle.",
499                  function );
500 
501 		goto on_error;
502 	}
503 	if( libesedb_file_open_file_io_handle(
504 	     file,
505 	     file_io_handle,
506 	     access_flags,
507 	     error ) != 1 )
508 	{
509 		libcerror_error_set(
510 		 error,
511 		 LIBCERROR_ERROR_DOMAIN_IO,
512 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
513 		 "%s: unable to open file: %ls.",
514 		 function,
515 		 filename );
516 
517 		goto on_error;
518 	}
519 	internal_file->file_io_handle_created_in_library = 1;
520 
521 	return( 1 );
522 
523 on_error:
524 	if( file_io_handle != NULL )
525 	{
526 		libbfio_handle_free(
527 		 &file_io_handle,
528 		 NULL );
529 	}
530 	return( -1 );
531 }
532 
533 #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
534 
535 /* Opens a file using a Basic File IO (bfio) handle
536  * Returns 1 if successful or -1 on error
537  */
libesedb_file_open_file_io_handle(libesedb_file_t * file,libbfio_handle_t * file_io_handle,int access_flags,libcerror_error_t ** error)538 int libesedb_file_open_file_io_handle(
539      libesedb_file_t *file,
540      libbfio_handle_t *file_io_handle,
541      int access_flags,
542      libcerror_error_t **error )
543 {
544 	libesedb_internal_file_t *internal_file = NULL;
545 	static char *function                   = "libesedb_file_open_file_io_handle";
546 	int bfio_access_flags                   = 0;
547 	int file_io_handle_is_open              = 0;
548 
549 	if( file == NULL )
550 	{
551 		libcerror_error_set(
552 		 error,
553 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
554 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
555 		 "%s: invalid file.",
556 		 function );
557 
558 		return( -1 );
559 	}
560 	if( file_io_handle == NULL )
561 	{
562 		libcerror_error_set(
563 		 error,
564 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
565 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
566 		 "%s: invalid file IO handle.",
567 		 function );
568 
569 		return( -1 );
570 	}
571 	if( ( ( access_flags & LIBESEDB_ACCESS_FLAG_READ ) == 0 )
572 	 && ( ( access_flags & LIBESEDB_ACCESS_FLAG_WRITE ) == 0 ) )
573 	{
574 		libcerror_error_set(
575 		 error,
576 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
577 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
578 		 "%s: unsupported access flags.",
579 		 function );
580 
581 		return( -1 );
582 	}
583 	if( ( access_flags & LIBESEDB_ACCESS_FLAG_WRITE ) != 0 )
584 	{
585 		libcerror_error_set(
586 		 error,
587 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
588 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
589 		 "%s: write access currently not supported.",
590 		 function );
591 
592 		return( -1 );
593 	}
594 	internal_file = (libesedb_internal_file_t *) file;
595 
596 	if( ( access_flags & LIBESEDB_ACCESS_FLAG_READ ) != 0 )
597 	{
598 		bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
599 	}
600 	file_io_handle_is_open = libbfio_handle_is_open(
601 	                          file_io_handle,
602 	                          error );
603 
604 	if( file_io_handle_is_open == -1 )
605 	{
606 		libcerror_error_set(
607 		 error,
608 		 LIBCERROR_ERROR_DOMAIN_IO,
609 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
610 		 "%s: unable to open file.",
611 		 function );
612 
613 		goto on_error;
614 	}
615 	else if( file_io_handle_is_open == 0 )
616 	{
617 		if( libbfio_handle_open(
618 		     file_io_handle,
619 		     bfio_access_flags,
620 		     error ) != 1 )
621 		{
622 			libcerror_error_set(
623 			 error,
624 			 LIBCERROR_ERROR_DOMAIN_IO,
625 			 LIBCERROR_IO_ERROR_OPEN_FAILED,
626 			 "%s: unable to open file IO handle.",
627 			 function );
628 
629 			goto on_error;
630 		}
631 		internal_file->file_io_handle_opened_in_library = 1;
632 	}
633 	if( libesedb_file_open_read(
634 	     internal_file,
635 	     file_io_handle,
636 	     error ) != 1 )
637 	{
638 		libcerror_error_set(
639 		 error,
640 		 LIBCERROR_ERROR_DOMAIN_IO,
641 		 LIBCERROR_IO_ERROR_READ_FAILED,
642 		 "%s: unable to read from file handle.",
643 		 function );
644 
645 		goto on_error;
646 	}
647 	internal_file->file_io_handle = file_io_handle;
648 
649 	return( 1 );
650 
651 on_error:
652 	if( ( file_io_handle_is_open == 0 )
653 	 && ( internal_file->file_io_handle_opened_in_library != 0 ) )
654 	{
655 		libbfio_handle_close(
656 		 file_io_handle,
657 		 error );
658 
659 		internal_file->file_io_handle_opened_in_library = 0;
660 	}
661 	return( -1 );
662 }
663 
664 /* Closes a file
665  * Returns 0 if successful or -1 on error
666  */
libesedb_file_close(libesedb_file_t * file,libcerror_error_t ** error)667 int libesedb_file_close(
668      libesedb_file_t *file,
669      libcerror_error_t **error )
670 {
671 	libesedb_internal_file_t *internal_file = NULL;
672 	static char *function                   = "libesedb_file_close";
673 	int result                              = 0;
674 
675 	if( file == NULL )
676 	{
677 		libcerror_error_set(
678 		 error,
679 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
680 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
681 		 "%s: invalid file.",
682 		 function );
683 
684 		return( -1 );
685 	}
686 	internal_file = (libesedb_internal_file_t *) file;
687 
688 	if( internal_file->file_io_handle == NULL )
689 	{
690 		libcerror_error_set(
691 		 error,
692 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
693 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
694 		 "%s: invalid file - missing file IO handle.",
695 		 function );
696 
697 		return( -1 );
698 	}
699 #if defined( HAVE_DEBUG_OUTPUT )
700 	if( libcnotify_verbose != 0 )
701 	{
702 		if( internal_file->file_io_handle_created_in_library != 0 )
703 		{
704 			if( libesedb_debug_print_read_offsets(
705 			     internal_file->file_io_handle,
706 			     error ) != 1 )
707 			{
708 				libcerror_error_set(
709 				 error,
710 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
711 				 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
712 				 "%s: unable to print the read offsets.",
713 				 function );
714 
715 				result = -1;
716 			}
717 		}
718 	}
719 #endif
720 	if( internal_file->file_io_handle_opened_in_library != 0 )
721 	{
722 		if( libbfio_handle_close(
723 		     internal_file->file_io_handle,
724 		     error ) != 0 )
725 		{
726 			libcerror_error_set(
727 			 error,
728 			 LIBCERROR_ERROR_DOMAIN_IO,
729 			 LIBCERROR_IO_ERROR_CLOSE_FAILED,
730 			 "%s: unable to close file IO handle.",
731 			 function );
732 
733 			result = -1;
734 		}
735 		internal_file->file_io_handle_opened_in_library = 0;
736 	}
737 	if( internal_file->file_io_handle_created_in_library != 0 )
738 	{
739 		if( libbfio_handle_free(
740 		     &( internal_file->file_io_handle ),
741 		     error ) != 1 )
742 		{
743 			libcerror_error_set(
744 			 error,
745 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
746 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
747 			 "%s: unable to free file IO handle.",
748 			 function );
749 
750 			result = -1;
751 		}
752 		internal_file->file_io_handle_created_in_library = 0;
753 	}
754 	internal_file->file_io_handle = NULL;
755 
756 	if( libesedb_io_handle_clear(
757 	     internal_file->io_handle,
758 	     error ) != 1 )
759 	{
760 		libcerror_error_set(
761 		 error,
762 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
763 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
764 		 "%s: unable to clear IO handle.",
765 		 function );
766 
767 		result = -1;
768 	}
769 	if( libfdata_vector_free(
770 	     &( internal_file->pages_vector ),
771 	     error ) != 1 )
772 	{
773 		libcerror_error_set(
774 		 error,
775 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
776 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
777 		 "%s: unable to free pages vector.",
778 		 function );
779 
780 		result = -1;
781 	}
782 	if( libfcache_cache_free(
783 	     &( internal_file->pages_cache ),
784 	     error ) != 1 )
785 	{
786 		libcerror_error_set(
787 		 error,
788 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
789 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
790 		 "%s: unable to free pages cache.",
791 		 function );
792 
793 		result = -1;
794 	}
795 	if( libesedb_database_free(
796 	     &( internal_file->database ),
797 	     error ) != 1 )
798 	{
799 		libcerror_error_set(
800 		 error,
801 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
802 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
803 		 "%s: unable to free database.",
804 		 function );
805 
806 		result = -1;
807 	}
808 	if( libesedb_catalog_free(
809 	     &( internal_file->catalog ),
810 	     error ) != 1 )
811 	{
812 		libcerror_error_set(
813 		 error,
814 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
815 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
816 		 "%s: unable to free catalog.",
817 		 function );
818 
819 		result = -1;
820 	}
821 	if( libesedb_catalog_free(
822 	     &( internal_file->backup_catalog ),
823 	     error ) != 1 )
824 	{
825 		libcerror_error_set(
826 		 error,
827 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
828 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
829 		 "%s: unable to free backup catalog.",
830 		 function );
831 
832 		result = -1;
833 	}
834 	return( result );
835 }
836 
837 /* Opens a file for reading
838  * Returns 1 if successful or -1 on error
839  */
libesedb_file_open_read(libesedb_internal_file_t * internal_file,libbfio_handle_t * file_io_handle,libcerror_error_t ** error)840 int libesedb_file_open_read(
841      libesedb_internal_file_t *internal_file,
842      libbfio_handle_t *file_io_handle,
843      libcerror_error_t **error )
844 {
845 	libesedb_file_header_t *file_header = NULL;
846 	static char *function               = "libesedb_file_open_read";
847 	size64_t file_size                  = 0;
848 	off64_t file_offset                 = 0;
849 	int result                          = 0;
850 	int segment_index                   = 0;
851 
852 	if( internal_file == NULL )
853 	{
854 		libcerror_error_set(
855 		 error,
856 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
857 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
858 		 "%s: invalid file.",
859 		 function );
860 
861 		return( -1 );
862 	}
863 	if( internal_file->io_handle == NULL )
864 	{
865 		libcerror_error_set(
866 		 error,
867 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
868 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
869 		 "%s: invalid file - missing IO handle.",
870 		 function );
871 
872 		return( -1 );
873 	}
874 	if( internal_file->pages_vector != NULL )
875 	{
876 		libcerror_error_set(
877 		 error,
878 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
879 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
880 		 "%s: invalid file - pages vector already set.",
881 		 function );
882 
883 		return( -1 );
884 	}
885 	if( internal_file->pages_cache != NULL )
886 	{
887 		libcerror_error_set(
888 		 error,
889 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
890 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
891 		 "%s: invalid file - pages cache already set.",
892 		 function );
893 
894 		return( -1 );
895 	}
896 	if( internal_file->database != NULL )
897 	{
898 		libcerror_error_set(
899 		 error,
900 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
901 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
902 		 "%s: invalid file - database already set.",
903 		 function );
904 
905 		return( -1 );
906 	}
907 	if( internal_file->catalog != NULL )
908 	{
909 		libcerror_error_set(
910 		 error,
911 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
912 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
913 		 "%s: invalid file - catalog already set.",
914 		 function );
915 
916 		return( -1 );
917 	}
918 	if( internal_file->backup_catalog != NULL )
919 	{
920 		libcerror_error_set(
921 		 error,
922 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
923 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
924 		 "%s: invalid file - backup catalog already set.",
925 		 function );
926 
927 		return( -1 );
928 	}
929 	internal_file->io_handle->abort = 0;
930 
931 	if( libbfio_handle_get_size(
932 	     file_io_handle,
933 	     &file_size,
934 	     error ) != 1 )
935 	{
936 		libcerror_error_set(
937 		 error,
938 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
939 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
940 		 "%s: unable to retrieve file size.",
941 		 function );
942 
943 		goto on_error;
944 	}
945 #if defined( HAVE_DEBUG_OUTPUT )
946 	if( libcnotify_verbose != 0 )
947 	{
948 		libcnotify_printf(
949 		 "Reading file header:\n" );
950 	}
951 #endif
952 	if( libesedb_file_header_initialize(
953 	     &file_header,
954 	     error ) != 1 )
955 	{
956 		libcerror_error_set(
957 		 error,
958 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
959 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
960 		 "%s: unable to create file header.",
961 		 function );
962 
963 		goto on_error;
964 	}
965 	if( libesedb_file_header_read_file_io_handle(
966 	     file_header,
967 	     file_io_handle,
968 	     file_offset,
969 	     error ) != 1 )
970 	{
971 		libcerror_error_set(
972 		 error,
973 		 LIBCERROR_ERROR_DOMAIN_IO,
974 		 LIBCERROR_IO_ERROR_READ_FAILED,
975 		 "%s: unable to read file header.",
976 		 function );
977 
978 		goto on_error;
979 	}
980 	internal_file->io_handle->file_type                = file_header->file_type;
981 	internal_file->io_handle->format_version           = file_header->format_version;
982 	internal_file->io_handle->format_revision          = file_header->format_revision;
983 	internal_file->io_handle->page_size                = file_header->page_size;
984 	internal_file->io_handle->creation_format_version  = file_header->creation_format_version;
985 	internal_file->io_handle->creation_format_revision = file_header->creation_format_revision;
986 
987 	if( libesedb_file_header_free(
988 	     &file_header,
989 	     error ) != 1 )
990 	{
991 		libcerror_error_set(
992 		 error,
993 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
994 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
995 		 "%s: unable to free file header.",
996 		 function );
997 
998 		goto on_error;
999 	}
1000 #if defined( HAVE_DEBUG_OUTPUT )
1001 	if( libcnotify_verbose != 0 )
1002 	{
1003 		libcnotify_printf(
1004 		 "Reading backup file header:\n" );
1005 	}
1006 #endif
1007 	if( internal_file->io_handle->page_size != 0 )
1008 	{
1009 		if( libesedb_file_header_initialize(
1010 		     &file_header,
1011 		     error ) != 1 )
1012 		{
1013 			libcerror_error_set(
1014 			 error,
1015 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1016 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1017 			 "%s: unable to create backup file header.",
1018 			 function );
1019 
1020 			goto on_error;
1021 		}
1022 		result = libesedb_file_header_read_file_io_handle(
1023 		          file_header,
1024 		          file_io_handle,
1025 		          (off64_t) internal_file->io_handle->page_size,
1026 		          error );
1027 
1028 		if( result != 1 )
1029 		{
1030 			file_offset = 0x0800;
1031 
1032 			while( file_offset <= 0x8000 )
1033 			{
1034 #if defined( HAVE_DEBUG_OUTPUT )
1035 				if( ( libcnotify_verbose != 0 )
1036 				 && ( error != NULL )
1037 				 && ( *error != NULL ) )
1038 				{
1039 					libcnotify_print_error_backtrace(
1040 					 *error );
1041 				}
1042 #endif
1043 				libcerror_error_free(
1044 				 error );
1045 
1046 				result = libesedb_file_header_read_file_io_handle(
1047 				          file_header,
1048 				          file_io_handle,
1049 				          (off64_t) internal_file->io_handle->page_size,
1050 				          error );
1051 
1052 				if( result == 1 )
1053 				{
1054 					break;
1055 				}
1056 				file_offset <<= 1;
1057 			}
1058 		}
1059 		if( result != 1 )
1060 		{
1061 			libcerror_error_set(
1062 			 error,
1063 			 LIBCERROR_ERROR_DOMAIN_IO,
1064 			 LIBCERROR_IO_ERROR_READ_FAILED,
1065 			 "%s: unable to read backup file header.",
1066 			 function );
1067 
1068 			goto on_error;
1069 		}
1070 		if( internal_file->io_handle->format_version == 0 )
1071 		{
1072 			internal_file->io_handle->format_version = file_header->format_version;
1073 		}
1074 		else if( internal_file->io_handle->format_version != file_header->format_version )
1075 		{
1076 #if defined( HAVE_VERBOSE_OUTPUT )
1077 			if( libcnotify_verbose != 0 )
1078 			{
1079 				libcnotify_printf(
1080 				 "%s: mismatch in format version: 0x%" PRIx32 " and backup: 0x%" PRIx32 "\n",
1081 				 function,
1082 				 internal_file->io_handle->format_version,
1083 				 file_header->format_version );
1084 			}
1085 #endif
1086 		}
1087 		if( internal_file->io_handle->format_revision == 0 )
1088 		{
1089 			internal_file->io_handle->format_revision = file_header->format_revision;
1090 		}
1091 		else if( internal_file->io_handle->format_revision != file_header->format_revision )
1092 		{
1093 #if defined( HAVE_VERBOSE_OUTPUT )
1094 			if( libcnotify_verbose != 0 )
1095 			{
1096 				libcnotify_printf(
1097 				 "%s: mismatch in format revision: 0x%" PRIx32 " and backup: 0x%" PRIx32 "\n",
1098 				 function,
1099 				 internal_file->io_handle->format_revision,
1100 				 file_header->format_revision );
1101 			}
1102 #endif
1103 		}
1104 		if( internal_file->io_handle->page_size == 0 )
1105 		{
1106 			internal_file->io_handle->page_size = file_header->page_size;
1107 		}
1108 		else if( internal_file->io_handle->page_size != file_header->page_size )
1109 		{
1110 #if defined( HAVE_VERBOSE_OUTPUT )
1111 			if( libcnotify_verbose != 0 )
1112 			{
1113 				libcnotify_printf(
1114 				 "%s: mismatch in page size: 0x%04" PRIx32 " and backup: 0x%04" PRIx32 "\n",
1115 				 function,
1116 				 internal_file->io_handle->page_size,
1117 				 file_header->page_size );
1118 			}
1119 #endif
1120 			/* The offset of the backup (database) file header
1121 			 * is a good indication of the actual page size
1122 			 */
1123 			internal_file->io_handle->page_size = (uint32_t) file_offset;
1124 		}
1125 		if( libesedb_file_header_free(
1126 		     &file_header,
1127 		     error ) != 1 )
1128 		{
1129 			libcerror_error_set(
1130 			 error,
1131 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1132 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1133 			 "%s: unable to free backup file header.",
1134 			 function );
1135 
1136 			goto on_error;
1137 		}
1138 	}
1139 	if( internal_file->io_handle->format_version != 0x620 )
1140 	{
1141 		libcerror_error_set(
1142 		 error,
1143 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1144 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1145 		 "%s: unsupported format version: 0x%04" PRIx32 ".",
1146 		 function,
1147 		 internal_file->io_handle->format_version );
1148 
1149 		goto on_error;
1150 	}
1151 	if( internal_file->io_handle->page_size == 0 )
1152 	{
1153 		libcerror_error_set(
1154 		 error,
1155 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1156 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1157 		 "%s: invalid page size.",
1158 		 function );
1159 
1160 		goto on_error;
1161 	}
1162 	if( internal_file->io_handle->format_version == 0x620 )
1163 	{
1164 		if( internal_file->io_handle->format_revision < 0x11 )
1165 		{
1166 			if( ( internal_file->io_handle->page_size != 0x1000 )
1167 			 && ( internal_file->io_handle->page_size != 0x2000 ) )
1168 			{
1169 				libcerror_error_set(
1170 				 error,
1171 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1172 				 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1173 				 "%s: unsupported page size: %" PRIu32 " (0x%04" PRIx32 ") for format version: 0x%" PRIx32 " revision: 0x%" PRIx32 ".",
1174 				 function,
1175 				 internal_file->io_handle->page_size,
1176 				 internal_file->io_handle->page_size,
1177 				 internal_file->io_handle->format_version,
1178 				 internal_file->io_handle->format_revision );
1179 
1180 				goto on_error;
1181 			}
1182 		}
1183 		else
1184 		{
1185 			if( ( internal_file->io_handle->page_size != 0x0800 )
1186 			 && ( internal_file->io_handle->page_size != 0x1000 )
1187 			 && ( internal_file->io_handle->page_size != 0x2000 )
1188 			 && ( internal_file->io_handle->page_size != 0x4000 )
1189 			 && ( internal_file->io_handle->page_size != 0x8000 ) )
1190 			{
1191 				libcerror_error_set(
1192 				 error,
1193 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1194 				 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1195 				 "%s: unsupported page size: %" PRIu32 " (0x%04" PRIx32 ") for format version: 0x%" PRIx32 " revision: 0x%" PRIx32 ".",
1196 				 function,
1197 				 internal_file->io_handle->page_size,
1198 				 internal_file->io_handle->page_size,
1199 				 internal_file->io_handle->format_version,
1200 				 internal_file->io_handle->format_revision );
1201 
1202 				goto on_error;
1203 			}
1204 		}
1205 	}
1206 	if( libesedb_io_handle_set_pages_data_range(
1207 	     internal_file->io_handle,
1208 	     file_size,
1209 	     error ) != 1 )
1210 	{
1211                 libcerror_error_set(
1212                  error,
1213                  LIBCERROR_ERROR_DOMAIN_RUNTIME,
1214                  LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1215                  "%s: unable to set pages data range in IO handle.",
1216                  function );
1217 
1218 		goto on_error;
1219 	}
1220 /* TODO add clone function ? */
1221 	if( libfdata_vector_initialize(
1222 	     &( internal_file->pages_vector ),
1223 	     (size64_t) internal_file->io_handle->page_size,
1224 	     (intptr_t *) internal_file->io_handle,
1225 	     NULL,
1226 	     NULL,
1227 	     (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libesedb_io_handle_read_page,
1228 	     NULL,
1229 	     LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
1230 	     error ) != 1 )
1231 	{
1232 		libcerror_error_set(
1233 		 error,
1234 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1235 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1236 		 "%s: unable to create pages vector.",
1237 		 function );
1238 
1239 		goto on_error;
1240 	}
1241 	if( libfdata_vector_append_segment(
1242 	     internal_file->pages_vector,
1243 	     &segment_index,
1244 	     0,
1245 	     internal_file->io_handle->pages_data_offset,
1246 	     internal_file->io_handle->pages_data_size,
1247 	     0,
1248 	     error ) != 1 )
1249 	{
1250 		libcerror_error_set(
1251 		 error,
1252 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1253 		 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1254 		 "%s: unable to append segment to pages vector.",
1255 		 function );
1256 
1257 		goto on_error;
1258 	}
1259 	if( libfcache_cache_initialize(
1260 	     &( internal_file->pages_cache ),
1261 	     LIBESEDB_MAXIMUM_CACHE_ENTRIES_PAGES,
1262 	     error ) != 1 )
1263 	{
1264 		libcerror_error_set(
1265 		 error,
1266 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1267 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1268 		 "%s: unable to create pages cache.",
1269 		 function );
1270 
1271 		goto on_error;
1272 	}
1273 	if( internal_file->io_handle->file_type == LIBESEDB_FILE_TYPE_DATABASE )
1274 	{
1275 #if defined( HAVE_DEBUG_OUTPUT )
1276 		if( libcnotify_verbose != 0 )
1277 		{
1278 			libcnotify_printf(
1279 			 "Reading the database:\n" );
1280 		}
1281 #endif
1282 		if( libesedb_database_initialize(
1283 		     &( internal_file->database ),
1284 		     internal_file->io_handle,
1285 		     internal_file->pages_vector,
1286 		     internal_file->pages_cache,
1287 		     error ) != 1 )
1288 		{
1289 			libcerror_error_set(
1290 			 error,
1291 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1292 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1293 			 "%s: unable to create database.",
1294 			 function );
1295 
1296 			goto on_error;
1297 		}
1298 		if( libesedb_database_read_file_io_handle(
1299 		     internal_file->database,
1300 		     file_io_handle,
1301 		     error ) != 1 )
1302 		{
1303 			libcerror_error_set(
1304 			 error,
1305 			 LIBCERROR_ERROR_DOMAIN_IO,
1306 			 LIBCERROR_IO_ERROR_READ_FAILED,
1307 			 "%s: unable to read database.",
1308 			 function );
1309 
1310 			goto on_error;
1311 		}
1312 #if defined( HAVE_DEBUG_OUTPUT )
1313 		if( libcnotify_verbose != 0 )
1314 		{
1315 			libcnotify_printf(
1316 			 "Reading the catalog:\n" );
1317 		}
1318 #endif
1319 		if( libesedb_catalog_initialize(
1320 		     &( internal_file->catalog ),
1321 		     internal_file->io_handle,
1322 		     LIBESEDB_PAGE_NUMBER_CATALOG,
1323 		     internal_file->pages_vector,
1324 		     internal_file->pages_cache,
1325 		     error ) != 1 )
1326 		{
1327 			libcerror_error_set(
1328 			 error,
1329 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1330 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1331 			 "%s: unable to create catalog.",
1332 			 function );
1333 
1334 			goto on_error;
1335 		}
1336 		if( libesedb_catalog_read_file_io_handle(
1337 		     internal_file->catalog,
1338 		     file_io_handle,
1339 		     error ) != 1 )
1340 		{
1341 			libcerror_error_set(
1342 			 error,
1343 			 LIBCERROR_ERROR_DOMAIN_IO,
1344 			 LIBCERROR_IO_ERROR_READ_FAILED,
1345 			 "%s: unable to read catalog.",
1346 			 function );
1347 
1348 			goto on_error;
1349 		}
1350 #if defined( HAVE_DEBUG_OUTPUT )
1351 		if( libcnotify_verbose != 0 )
1352 		{
1353 			libcnotify_printf(
1354 			 "Reading the backup catalog:\n" );
1355 		}
1356 #endif
1357 		if( libesedb_catalog_initialize(
1358 		     &( internal_file->backup_catalog ),
1359 		     internal_file->io_handle,
1360 		     LIBESEDB_PAGE_NUMBER_CATALOG_BACKUP,
1361 		     internal_file->pages_vector,
1362 		     internal_file->pages_cache,
1363 		     error ) != 1 )
1364 		{
1365 			libcerror_error_set(
1366 			 error,
1367 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1368 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1369 			 "%s: unable to create backup catalog.",
1370 			 function );
1371 
1372 			goto on_error;
1373 		}
1374 		if( libesedb_catalog_read_file_io_handle(
1375 		     internal_file->backup_catalog,
1376 		     file_io_handle,
1377 		     error ) != 1 )
1378 		{
1379 			libcerror_error_set(
1380 			 error,
1381 			 LIBCERROR_ERROR_DOMAIN_IO,
1382 			 LIBCERROR_IO_ERROR_READ_FAILED,
1383 			 "%s: unable to read backup catalog.",
1384 			 function );
1385 
1386 			goto on_error;
1387 		}
1388 /* TODO compare contents of catalogs ? */
1389 	}
1390 	internal_file->io_handle->abort = 0;
1391 
1392 	return( 1 );
1393 
1394 on_error:
1395 	if( internal_file->backup_catalog != NULL )
1396 	{
1397 		libesedb_catalog_free(
1398 		 &( internal_file->backup_catalog ),
1399 		 NULL );
1400 	}
1401 	if( internal_file->catalog != NULL )
1402 	{
1403 		libesedb_catalog_free(
1404 		 &( internal_file->catalog ),
1405 		 NULL );
1406 	}
1407 	if( internal_file->database != NULL )
1408 	{
1409 		libesedb_database_free(
1410 		 &( internal_file->database ),
1411 		 NULL );
1412 	}
1413 	if( internal_file->pages_cache != NULL )
1414 	{
1415 		libfcache_cache_free(
1416 		 &( internal_file->pages_cache ),
1417 		 NULL );
1418 	}
1419 	if( internal_file->pages_vector != NULL )
1420 	{
1421 		libfdata_vector_free(
1422 		 &( internal_file->pages_vector ),
1423 		 NULL );
1424 	}
1425 	if( file_header != NULL )
1426 	{
1427 		libesedb_file_header_free(
1428 		 &file_header,
1429 		 NULL );
1430 	}
1431 	internal_file->io_handle->abort = 0;
1432 
1433 	return( -1 );
1434 }
1435 
1436 /* Retrieves the file type
1437  * Returns 1 if successful or -1 on error
1438  */
libesedb_file_get_type(libesedb_file_t * file,uint32_t * type,libcerror_error_t ** error)1439 int libesedb_file_get_type(
1440      libesedb_file_t *file,
1441      uint32_t *type,
1442      libcerror_error_t **error )
1443 {
1444 	libesedb_internal_file_t *internal_file = NULL;
1445 	static char *function                   = "libesedb_file_get_type";
1446 
1447 	if( file == NULL )
1448 	{
1449 		libcerror_error_set(
1450 		 error,
1451 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1452 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1453 		 "%s: invalid file.",
1454 		 function );
1455 
1456 		return( -1 );
1457 	}
1458 	internal_file = (libesedb_internal_file_t *) file;
1459 
1460 	if( internal_file->io_handle == NULL )
1461 	{
1462 		libcerror_error_set(
1463 		 error,
1464 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1465 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1466 		 "%s: invalid file - missing IO handle.",
1467 		 function );
1468 
1469 		return( -1 );
1470 	}
1471 	if( type == NULL )
1472 	{
1473 		libcerror_error_set(
1474 		 error,
1475 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1476 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1477 		 "%s: invalid type.",
1478 		 function );
1479 
1480 		return( -1 );
1481 	}
1482 	*type = internal_file->io_handle->file_type;
1483 
1484 	return( 1 );
1485 }
1486 
1487 /* Retrieves the file (current) version
1488  * Returns 1 if successful or -1 on error
1489  */
libesedb_file_get_format_version(libesedb_file_t * file,uint32_t * format_version,uint32_t * format_revision,libcerror_error_t ** error)1490 int libesedb_file_get_format_version(
1491      libesedb_file_t *file,
1492      uint32_t *format_version,
1493      uint32_t *format_revision,
1494      libcerror_error_t **error )
1495 {
1496 	libesedb_internal_file_t *internal_file = NULL;
1497 	static char *function                   = "libesedb_file_get_format_version";
1498 
1499 	if( file == NULL )
1500 	{
1501 		libcerror_error_set(
1502 		 error,
1503 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1504 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1505 		 "%s: invalid file.",
1506 		 function );
1507 
1508 		return( -1 );
1509 	}
1510 	internal_file = (libesedb_internal_file_t *) file;
1511 
1512 	if( internal_file->io_handle == NULL )
1513 	{
1514 		libcerror_error_set(
1515 		 error,
1516 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1517 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1518 		 "%s: invalid file - missing IO handle.",
1519 		 function );
1520 
1521 		return( -1 );
1522 	}
1523 	if( format_version == NULL )
1524 	{
1525 		libcerror_error_set(
1526 		 error,
1527 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1528 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1529 		 "%s: invalid format version.",
1530 		 function );
1531 
1532 		return( -1 );
1533 	}
1534 	if( format_revision == NULL )
1535 	{
1536 		libcerror_error_set(
1537 		 error,
1538 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1539 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1540 		 "%s: invalid format revision.",
1541 		 function );
1542 
1543 		return( -1 );
1544 	}
1545 	*format_version  = internal_file->io_handle->format_version;
1546 	*format_revision = internal_file->io_handle->format_revision;
1547 
1548 	return( 1 );
1549 }
1550 
1551 /* Retrieves the file creation format version
1552  * Returns 1 if successful or -1 on error
1553  */
libesedb_file_get_creation_format_version(libesedb_file_t * file,uint32_t * format_version,uint32_t * format_revision,libcerror_error_t ** error)1554 int libesedb_file_get_creation_format_version(
1555      libesedb_file_t *file,
1556      uint32_t *format_version,
1557      uint32_t *format_revision,
1558      libcerror_error_t **error )
1559 {
1560 	libesedb_internal_file_t *internal_file = NULL;
1561 	static char *function                   = "libesedb_file_get_creation_format_version";
1562 
1563 	if( file == NULL )
1564 	{
1565 		libcerror_error_set(
1566 		 error,
1567 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1568 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1569 		 "%s: invalid file.",
1570 		 function );
1571 
1572 		return( -1 );
1573 	}
1574 	internal_file = (libesedb_internal_file_t *) file;
1575 
1576 	if( internal_file->io_handle == NULL )
1577 	{
1578 		libcerror_error_set(
1579 		 error,
1580 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1581 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1582 		 "%s: invalid file - missing IO handle.",
1583 		 function );
1584 
1585 		return( -1 );
1586 	}
1587 	if( format_version == NULL )
1588 	{
1589 		libcerror_error_set(
1590 		 error,
1591 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1592 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1593 		 "%s: invalid format version.",
1594 		 function );
1595 
1596 		return( -1 );
1597 	}
1598 	if( format_revision == NULL )
1599 	{
1600 		libcerror_error_set(
1601 		 error,
1602 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1603 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1604 		 "%s: invalid format revision.",
1605 		 function );
1606 
1607 		return( -1 );
1608 	}
1609 	*format_version  = internal_file->io_handle->creation_format_version;
1610 	*format_revision = internal_file->io_handle->creation_format_revision;
1611 
1612 	return( 1 );
1613 }
1614 
1615 /* Retrieves the file page size
1616  * Returns 1 if successful or -1 on error
1617  */
libesedb_file_get_page_size(libesedb_file_t * file,uint32_t * page_size,libcerror_error_t ** error)1618 int libesedb_file_get_page_size(
1619      libesedb_file_t *file,
1620      uint32_t *page_size,
1621      libcerror_error_t **error )
1622 {
1623 	libesedb_internal_file_t *internal_file = NULL;
1624 	static char *function                   = "libesedb_file_get_page_size";
1625 
1626 	if( file == NULL )
1627 	{
1628 		libcerror_error_set(
1629 		 error,
1630 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1631 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1632 		 "%s: invalid file.",
1633 		 function );
1634 
1635 		return( -1 );
1636 	}
1637 	internal_file = (libesedb_internal_file_t *) file;
1638 
1639 	if( internal_file->io_handle == NULL )
1640 	{
1641 		libcerror_error_set(
1642 		 error,
1643 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1644 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1645 		 "%s: invalid file - missing IO handle.",
1646 		 function );
1647 
1648 		return( -1 );
1649 	}
1650 	if( page_size == NULL )
1651 	{
1652 		libcerror_error_set(
1653 		 error,
1654 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1655 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1656 		 "%s: invalid page size.",
1657 		 function );
1658 
1659 		return( -1 );
1660 	}
1661 	*page_size = internal_file->io_handle->page_size;
1662 
1663 	return( 1 );
1664 }
1665 
1666 /* Retrieves the number of tables
1667  * Returns 1 if successful or -1 on error
1668  */
libesedb_file_get_number_of_tables(libesedb_file_t * file,int * number_of_tables,libcerror_error_t ** error)1669 int libesedb_file_get_number_of_tables(
1670      libesedb_file_t *file,
1671      int *number_of_tables,
1672      libcerror_error_t **error )
1673 {
1674 	libesedb_internal_file_t *internal_file = NULL;
1675 	static char *function                   = "libesedb_file_get_number_of_tables";
1676 
1677 	if( file == NULL )
1678 	{
1679 		libcerror_error_set(
1680 		 error,
1681 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1682 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1683 		 "%s: invalid file.",
1684 		 function );
1685 
1686 		return( -1 );
1687 	}
1688 	internal_file = (libesedb_internal_file_t *) file;
1689 
1690 	if( internal_file->catalog == NULL )
1691 	{
1692 		if( number_of_tables == NULL )
1693 		{
1694 			libcerror_error_set(
1695 			 error,
1696 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1697 			 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1698 			 "%s: invalid number of tables.",
1699 			 function );
1700 
1701 			return( -1 );
1702 		}
1703 		*number_of_tables = 0;
1704 	}
1705 	else
1706 	{
1707 		if( libesedb_catalog_get_number_of_table_definitions(
1708 		     internal_file->catalog,
1709 		     number_of_tables,
1710 		     error ) != 1 )
1711 		{
1712 			libcerror_error_set(
1713 			 error,
1714 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1715 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1716 			 "%s: unable to retrieve number of tables.",
1717 			 function );
1718 
1719 			return( -1 );
1720 		}
1721 	}
1722 	return( 1 );
1723 }
1724 
1725 /* Retrieves a specific table
1726  * Returns 1 if successful or -1 on error
1727  */
libesedb_file_get_table(libesedb_file_t * file,int table_entry,libesedb_table_t ** table,libcerror_error_t ** error)1728 int libesedb_file_get_table(
1729      libesedb_file_t *file,
1730      int table_entry,
1731      libesedb_table_t **table,
1732      libcerror_error_t **error )
1733 {
1734 	libesedb_internal_file_t *internal_file                = NULL;
1735 	libesedb_table_definition_t *table_definition          = NULL;
1736 	libesedb_table_definition_t *template_table_definition = NULL;
1737 	static char *function                                  = "libesedb_file_get_table";
1738 
1739 	if( file == NULL )
1740 	{
1741 		libcerror_error_set(
1742 		 error,
1743 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1744 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1745 		 "%s: invalid file.",
1746 		 function );
1747 
1748 		return( -1 );
1749 	}
1750 	internal_file = (libesedb_internal_file_t *) file;
1751 
1752 	if( table == NULL )
1753 	{
1754 		libcerror_error_set(
1755 		 error,
1756 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1757 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1758 		 "%s: invalid table.",
1759 		 function );
1760 
1761 		return( -1 );
1762 	}
1763 	if( *table != NULL )
1764 	{
1765 		libcerror_error_set(
1766 		 error,
1767 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1768 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1769 		 "%s: invalid table value already set.",
1770 		 function );
1771 
1772 		return( -1 );
1773 	}
1774 	if( libesedb_catalog_get_table_definition_by_index(
1775 	     internal_file->catalog,
1776 	     table_entry,
1777 	     &table_definition,
1778 	     error ) != 1 )
1779 	{
1780 		libcerror_error_set(
1781 		 error,
1782 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1783 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1784 		 "%s: unable to retrieve table definition: %d.",
1785 		 function,
1786 		 table_entry );
1787 
1788 		return( -1 );
1789 	}
1790 	if( table_definition == NULL )
1791 	{
1792 		libcerror_error_set(
1793 		 error,
1794 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1795 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1796 		 "%s: missing table definition.",
1797 		 function );
1798 
1799 		return( -1 );
1800 	}
1801 	if( table_definition->table_catalog_definition == NULL )
1802 	{
1803 		libcerror_error_set(
1804 		 error,
1805 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1806 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1807 		 "%s: invalid table definition - missing table catalog definition.",
1808 		 function );
1809 
1810 		return( -1 );
1811 	}
1812 	if( table_definition->table_catalog_definition->template_name != NULL )
1813 	{
1814 		if( libesedb_catalog_get_table_definition_by_utf8_name(
1815 		     internal_file->catalog,
1816 		     table_definition->table_catalog_definition->template_name,
1817 		     table_definition->table_catalog_definition->template_name_size,
1818 		     &template_table_definition,
1819 		     error ) != 1 )
1820 		{
1821 			libcerror_error_set(
1822 			 error,
1823 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1824 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1825 			 "%s: unable to retrieve template table definition.",
1826 			 function );
1827 
1828 			return( -1 );
1829 		}
1830 	}
1831 	if( libesedb_table_initialize(
1832 	     table,
1833 	     internal_file->file_io_handle,
1834 	     internal_file->io_handle,
1835 	     table_definition,
1836 	     template_table_definition,
1837 	     error ) != 1 )
1838 	{
1839 		libcerror_error_set(
1840 		 error,
1841 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1842 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1843 		 "%s: unable to create table.",
1844 		 function );
1845 
1846 		return( -1 );
1847 	}
1848 	return( 1 );
1849 }
1850 
1851 /* Retrieves the table for the UTF-8 encoded name
1852  * Returns 1 if successful, 0 if no table could be found or -1 on error
1853  */
libesedb_file_get_table_by_utf8_name(libesedb_file_t * file,const uint8_t * utf8_string,size_t utf8_string_length,libesedb_table_t ** table,libcerror_error_t ** error)1854 int libesedb_file_get_table_by_utf8_name(
1855      libesedb_file_t *file,
1856      const uint8_t *utf8_string,
1857      size_t utf8_string_length,
1858      libesedb_table_t **table,
1859      libcerror_error_t **error )
1860 {
1861 	libesedb_internal_file_t *internal_file                = NULL;
1862 	libesedb_table_definition_t *table_definition          = NULL;
1863 	libesedb_table_definition_t *template_table_definition = NULL;
1864 	static char *function                                  = "libesedb_file_get_table_by_utf8_name";
1865 	int result                                             = 0;
1866 
1867 	if( file == NULL )
1868 	{
1869 		libcerror_error_set(
1870 		 error,
1871 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1872 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1873 		 "%s: invalid file.",
1874 		 function );
1875 
1876 		return( -1 );
1877 	}
1878 	internal_file = (libesedb_internal_file_t *) file;
1879 
1880 	if( table == NULL )
1881 	{
1882 		libcerror_error_set(
1883 		 error,
1884 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1885 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1886 		 "%s: invalid table.",
1887 		 function );
1888 
1889 		return( -1 );
1890 	}
1891 	if( *table != NULL )
1892 	{
1893 		libcerror_error_set(
1894 		 error,
1895 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1896 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1897 		 "%s: invalid table value already set.",
1898 		 function );
1899 
1900 		return( -1 );
1901 	}
1902 	result = libesedb_catalog_get_table_definition_by_utf8_name(
1903 	          internal_file->catalog,
1904 	          utf8_string,
1905 	          utf8_string_length,
1906 	          &table_definition,
1907 	          error );
1908 
1909 	if( result == -1 )
1910 	{
1911 		libcerror_error_set(
1912 		 error,
1913 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1914 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1915 		 "%s: unable to retrieve table definition.",
1916 		 function );
1917 
1918 		return( -1 );
1919 	}
1920 	else if( result != 0 )
1921 	{
1922 		if( table_definition == NULL )
1923 		{
1924 			libcerror_error_set(
1925 			 error,
1926 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1927 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1928 			 "%s: missing table definition.",
1929 			 function );
1930 
1931 			return( -1 );
1932 		}
1933 		if( table_definition->table_catalog_definition == NULL )
1934 		{
1935 			libcerror_error_set(
1936 			 error,
1937 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1938 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1939 			 "%s: invalid table definition - missing table catalog definition.",
1940 			 function );
1941 
1942 			return( -1 );
1943 		}
1944 		if( table_definition->table_catalog_definition->template_name != NULL )
1945 		{
1946 			if( libesedb_catalog_get_table_definition_by_name(
1947 			     internal_file->catalog,
1948 			     table_definition->table_catalog_definition->template_name,
1949 			     table_definition->table_catalog_definition->template_name_size,
1950 			     &template_table_definition,
1951 			     error ) != 1 )
1952 			{
1953 				libcerror_error_set(
1954 				 error,
1955 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1956 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1957 				 "%s: unable to retrieve template table definition.",
1958 				 function );
1959 
1960 				return( -1 );
1961 			}
1962 		}
1963 		if( libesedb_table_initialize(
1964 		     table,
1965 		     internal_file->file_io_handle,
1966 		     internal_file->io_handle,
1967 		     table_definition,
1968 		     template_table_definition,
1969 		     error ) != 1 )
1970 		{
1971 			libcerror_error_set(
1972 			 error,
1973 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1974 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1975 			 "%s: unable to create table.",
1976 			 function );
1977 
1978 			return( -1 );
1979 		}
1980 	}
1981 	return( result );
1982 }
1983 
1984 /* Retrieves the table for the UTF-16 encoded name
1985  * Returns 1 if successful, 0 if no table could be found or -1 on error
1986  */
libesedb_file_get_table_by_utf16_name(libesedb_file_t * file,const uint16_t * utf16_string,size_t utf16_string_length,libesedb_table_t ** table,libcerror_error_t ** error)1987 int libesedb_file_get_table_by_utf16_name(
1988      libesedb_file_t *file,
1989      const uint16_t *utf16_string,
1990      size_t utf16_string_length,
1991      libesedb_table_t **table,
1992      libcerror_error_t **error )
1993 {
1994 	libesedb_internal_file_t *internal_file                = NULL;
1995 	libesedb_table_definition_t *table_definition          = NULL;
1996 	libesedb_table_definition_t *template_table_definition = NULL;
1997 	static char *function                                  = "libesedb_file_get_table_by_utf16_name";
1998 	int result                                             = 0;
1999 
2000 	if( file == NULL )
2001 	{
2002 		libcerror_error_set(
2003 		 error,
2004 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2005 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2006 		 "%s: invalid file.",
2007 		 function );
2008 
2009 		return( -1 );
2010 	}
2011 	internal_file = (libesedb_internal_file_t *) file;
2012 
2013 	if( table == NULL )
2014 	{
2015 		libcerror_error_set(
2016 		 error,
2017 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2018 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2019 		 "%s: invalid table.",
2020 		 function );
2021 
2022 		return( -1 );
2023 	}
2024 	if( *table != NULL )
2025 	{
2026 		libcerror_error_set(
2027 		 error,
2028 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2029 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2030 		 "%s: invalid table value already set.",
2031 		 function );
2032 
2033 		return( -1 );
2034 	}
2035 	result = libesedb_catalog_get_table_definition_by_utf16_name(
2036 	          internal_file->catalog,
2037 	          utf16_string,
2038 	          utf16_string_length,
2039 	          &table_definition,
2040 	          error );
2041 
2042 	if( result == -1 )
2043 	{
2044 		libcerror_error_set(
2045 		 error,
2046 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2047 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2048 		 "%s: unable to retrieve table definition.",
2049 		 function );
2050 
2051 		return( -1 );
2052 	}
2053 	else if( result != 0 )
2054 	{
2055 		if( table_definition == NULL )
2056 		{
2057 			libcerror_error_set(
2058 			 error,
2059 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2060 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2061 			 "%s: missing table definition.",
2062 			 function );
2063 
2064 			return( -1 );
2065 		}
2066 		if( table_definition->table_catalog_definition == NULL )
2067 		{
2068 			libcerror_error_set(
2069 			 error,
2070 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2071 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2072 			 "%s: invalid table definition - missing table catalog definition.",
2073 			 function );
2074 
2075 			return( -1 );
2076 		}
2077 		if( table_definition->table_catalog_definition->template_name != NULL )
2078 		{
2079 			if( libesedb_catalog_get_table_definition_by_name(
2080 			     internal_file->catalog,
2081 			     table_definition->table_catalog_definition->template_name,
2082 			     table_definition->table_catalog_definition->template_name_size,
2083 			     &template_table_definition,
2084 			     error ) != 1 )
2085 			{
2086 				libcerror_error_set(
2087 				 error,
2088 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2089 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2090 				 "%s: unable to retrieve template table definition.",
2091 				 function );
2092 
2093 				return( -1 );
2094 			}
2095 		}
2096 		if( libesedb_table_initialize(
2097 		     table,
2098 		     internal_file->file_io_handle,
2099 		     internal_file->io_handle,
2100 		     table_definition,
2101 		     template_table_definition,
2102 		     error ) != 1 )
2103 		{
2104 			libcerror_error_set(
2105 			 error,
2106 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2107 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2108 			 "%s: unable to create table.",
2109 			 function );
2110 
2111 			return( -1 );
2112 		}
2113 	}
2114 	return( result );
2115 }
2116 
2117