1 /*
2  * Catalog 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 <types.h>
25 
26 #include "libesedb_data_definition.h"
27 #include "libesedb_debug.h"
28 #include "libesedb_definitions.h"
29 #include "libesedb_catalog.h"
30 #include "libesedb_catalog_definition.h"
31 #include "libesedb_libbfio.h"
32 #include "libesedb_libcdata.h"
33 #include "libesedb_libcerror.h"
34 #include "libesedb_libcnotify.h"
35 #include "libesedb_libfcache.h"
36 #include "libesedb_libfdata.h"
37 #include "libesedb_libuna.h"
38 #include "libesedb_page_tree.h"
39 #include "libesedb_table_definition.h"
40 
41 /* Creates a catalog
42  * Make sure the value catalog is referencing, is set to NULL
43  * Returns 1 if successful or -1 on error
44  */
libesedb_catalog_initialize(libesedb_catalog_t ** catalog,libesedb_io_handle_t * io_handle,uint32_t root_page_number,libfdata_vector_t * pages_vector,libfcache_cache_t * pages_cache,libcerror_error_t ** error)45 int libesedb_catalog_initialize(
46      libesedb_catalog_t **catalog,
47      libesedb_io_handle_t *io_handle,
48      uint32_t root_page_number,
49      libfdata_vector_t *pages_vector,
50      libfcache_cache_t *pages_cache,
51      libcerror_error_t **error )
52 {
53 	static char *function = "libesedb_catalog_initialize";
54 
55 	if( catalog == NULL )
56 	{
57 		libcerror_error_set(
58 		 error,
59 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
60 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
61 		 "%s: invalid catalog.",
62 		 function );
63 
64 		return( -1 );
65 	}
66 	if( *catalog != NULL )
67 	{
68 		libcerror_error_set(
69 		 error,
70 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
71 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
72 		 "%s: invalid catalog value already set.",
73 		 function );
74 
75 		return( -1 );
76 	}
77 	*catalog = memory_allocate_structure(
78 	            libesedb_catalog_t );
79 
80 	if( *catalog == NULL )
81 	{
82 		libcerror_error_set(
83 		 error,
84 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
85 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
86 		 "%s: unable to create catalog.",
87 		 function );
88 
89 		goto on_error;
90 	}
91 	if( memory_set(
92 	     *catalog,
93 	     0,
94 	     sizeof( libesedb_catalog_t ) ) == NULL )
95 	{
96 		libcerror_error_set(
97 		 error,
98 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
99 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
100 		 "%s: unable to clear catalog.",
101 		 function );
102 
103 		memory_free(
104 		 *catalog );
105 
106 		*catalog = NULL;
107 
108 		return( -1 );
109 	}
110 	if( libesedb_page_tree_initialize(
111 	     &( ( *catalog )->page_tree ),
112 	     io_handle,
113 	     pages_vector,
114 	     pages_cache,
115 	     LIBESEDB_FDP_OBJECT_IDENTIFIER_CATALOG,
116 	     root_page_number,
117 	     NULL,
118 	     NULL,
119 	     error ) != 1 )
120 	{
121 		libcerror_error_set(
122 		 error,
123 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
124 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
125 		 "%s: unable to create page tree.",
126 		 function );
127 
128 		goto on_error;
129 	}
130 	if( libcdata_array_initialize(
131 	     &( ( *catalog )->table_definition_array ),
132 	     0,
133 	     error ) != 1 )
134 	{
135 		libcerror_error_set(
136 		 error,
137 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
138 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
139 		 "%s: unable to create table definition array.",
140 		 function );
141 
142 		goto on_error;
143 	}
144 	return( 1 );
145 
146 on_error:
147 	if( *catalog != NULL )
148 	{
149 		if( ( *catalog )->page_tree != NULL )
150 		{
151 			libesedb_page_tree_free(
152 			 &( ( *catalog )->page_tree ),
153 			 NULL );
154 		}
155 		memory_free(
156 		 *catalog );
157 
158 		*catalog = NULL;
159 	}
160 	return( -1 );
161 }
162 
163 /* Frees a catalog
164  * Returns 1 if successful or -1 on error
165  */
libesedb_catalog_free(libesedb_catalog_t ** catalog,libcerror_error_t ** error)166 int libesedb_catalog_free(
167      libesedb_catalog_t **catalog,
168      libcerror_error_t **error )
169 {
170 	static char *function = "libesedb_catalog_free";
171 	int result            = 1;
172 
173 	if( catalog == NULL )
174 	{
175 		libcerror_error_set(
176 		 error,
177 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
178 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
179 		 "%s: invalid catalog.",
180 		 function );
181 
182 		return( -1 );
183 	}
184 	if( *catalog != NULL )
185 	{
186 		if( libesedb_page_tree_free(
187 		     &( ( *catalog )->page_tree ),
188 		     error ) != 1 )
189 		{
190 			libcerror_error_set(
191 			 error,
192 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
193 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
194 			 "%s: unable to free catalog page tree.",
195 			 function );
196 
197 			result = -1;
198 		}
199 		if( libcdata_array_free(
200 		     &( ( *catalog )->table_definition_array ),
201 		     (int (*)(intptr_t **, libcerror_error_t **)) &libesedb_table_definition_free,
202 		     error ) != 1 )
203 		{
204 			libcerror_error_set(
205 			 error,
206 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
207 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
208 			 "%s: unable to free table definition array.",
209 			 function );
210 
211 			result = -1;
212 		}
213 		memory_free(
214 		 *catalog );
215 
216 		*catalog = NULL;
217 	}
218 	return( result );
219 }
220 
221 /* Reads a catalog value
222  * Returns 1 if successful or -1 on error
223  */
libesedb_catalog_read_value_data(libesedb_catalog_t * catalog,const uint8_t * data,size_t data_size,libesedb_table_definition_t ** table_definition,libcerror_error_t ** error)224 int libesedb_catalog_read_value_data(
225      libesedb_catalog_t *catalog,
226      const uint8_t *data,
227      size_t data_size,
228      libesedb_table_definition_t **table_definition,
229      libcerror_error_t **error )
230 {
231 	libesedb_catalog_definition_t *catalog_definition = NULL;
232 	static char *function                             = "libesedb_catalog_read_value_data";
233 	int entry_index                                   = 0;
234 
235 	if( catalog == NULL )
236 	{
237 		libcerror_error_set(
238 		 error,
239 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
240 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
241 		 "%s: invalid catalog.",
242 		 function );
243 
244 		return( -1 );
245 	}
246 	if( catalog->page_tree == NULL )
247 	{
248 		libcerror_error_set(
249 		 error,
250 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
251 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
252 		 "%s: invalid catalog - missing page tree.",
253 		 function );
254 
255 		return( -1 );
256 	}
257 	if( catalog->page_tree->io_handle == NULL )
258 	{
259 		libcerror_error_set(
260 		 error,
261 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
262 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
263 		 "%s: invalid catalog - invalid page tree - missing IO handle.",
264 		 function );
265 
266 		return( -1 );
267 	}
268 	if( table_definition == NULL )
269 	{
270 		libcerror_error_set(
271 		 error,
272 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
273 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
274 		 "%s: invalid table definition.",
275 		 function );
276 
277 		return( -1 );
278 	}
279 	if( libesedb_catalog_definition_initialize(
280 	     &catalog_definition,
281 	     error ) != 1 )
282 	{
283 		libcerror_error_set(
284 		 error,
285 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
286 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
287 		 "%s: unable to create catalog definition.",
288 		 function );
289 
290 		goto on_error;
291 	}
292 	if( libesedb_catalog_definition_read_data(
293 	     catalog_definition,
294 	     data,
295 	     data_size,
296 	     catalog->page_tree->io_handle->ascii_codepage,
297 	     error ) != 1 )
298 	{
299 		libcerror_error_set(
300 		 error,
301 		 LIBCERROR_ERROR_DOMAIN_IO,
302 		 LIBCERROR_IO_ERROR_READ_FAILED,
303 		 "%s: unable to read catalog definition.",
304 		 function );
305 
306 		goto on_error;
307 	}
308 	if( ( catalog_definition->type != LIBESEDB_CATALOG_DEFINITION_TYPE_TABLE )
309 	 && ( *table_definition == NULL ) )
310 	{
311 /* TODO add build-in table 1 support */
312 #if defined( HAVE_DEBUG_OUTPUT )
313 		if( libcnotify_verbose != 0 )
314 		{
315 			libcnotify_printf(
316 			 "%s: missing table definition for catalog definition type: %" PRIu16 ".\n",
317 			 function,
318 			 catalog_definition->type );
319 		}
320 #endif
321 		if( libesedb_catalog_definition_free(
322 		     &catalog_definition,
323 		     error ) != 1 )
324 		{
325 			libcerror_error_set(
326 			 error,
327 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
328 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
329 			 "%s: unable to free catalog definition.",
330 			 function );
331 
332 			goto on_error;
333 		}
334 		catalog_definition = NULL;
335 	}
336 	else switch( catalog_definition->type )
337 	{
338 		case LIBESEDB_CATALOG_DEFINITION_TYPE_TABLE:
339 			*table_definition = NULL;
340 
341 			if( libesedb_table_definition_initialize(
342 			     table_definition,
343 			     catalog_definition,
344 			     error ) != 1 )
345 			{
346 				libcerror_error_set(
347 				 error,
348 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
349 				 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
350 				 "%s: unable to create table definition.",
351 				 function );
352 
353 				libesedb_table_definition_free(
354 				 table_definition,
355 				 NULL );
356 
357 				goto on_error;
358 			}
359 			catalog_definition = NULL;
360 
361 			if( libcdata_array_append_entry(
362 			     catalog->table_definition_array,
363 			     &entry_index,
364 			     (intptr_t *) *table_definition,
365 			     error ) != 1 )
366 			{
367 				libcerror_error_set(
368 				 error,
369 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
370 				 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
371 				 "%s: unable to append table definition to table definition array.",
372 				 function );
373 
374 				libesedb_table_definition_free(
375 				 table_definition,
376 				 NULL );
377 
378 				goto on_error;
379 			}
380 			break;
381 
382 		case LIBESEDB_CATALOG_DEFINITION_TYPE_COLUMN:
383 			if( libesedb_table_definition_append_column_catalog_definition(
384 			     *table_definition,
385 			     catalog_definition,
386 			     error ) != 1 )
387 			{
388 				libcerror_error_set(
389 				 error,
390 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
391 				 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
392 				 "%s: unable to append column catalog definition to table definition.",
393 				 function );
394 
395 				goto on_error;
396 			}
397 			catalog_definition = NULL;
398 
399 			break;
400 
401 		case LIBESEDB_CATALOG_DEFINITION_TYPE_INDEX:
402 			if( libesedb_table_definition_append_index_catalog_definition(
403 			     *table_definition,
404 			     catalog_definition,
405 			     error ) != 1 )
406 			{
407 				libcerror_error_set(
408 				 error,
409 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
410 				 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
411 				 "%s: unable to append index catalog definition to table definition.",
412 				 function );
413 
414 				goto on_error;
415 			}
416 			catalog_definition = NULL;
417 
418 			break;
419 
420 		case LIBESEDB_CATALOG_DEFINITION_TYPE_LONG_VALUE:
421 			if( libesedb_table_definition_set_long_value_catalog_definition(
422 			     *table_definition,
423 			     catalog_definition,
424 			     error ) != 1 )
425 			{
426 				libcerror_error_set(
427 				 error,
428 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
429 				 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
430 				 "%s: unable to set long value catalog definition in table definition.",
431 				 function );
432 
433 				goto on_error;
434 			}
435 			catalog_definition = NULL;
436 
437 			break;
438 
439 		case LIBESEDB_CATALOG_DEFINITION_TYPE_CALLBACK:
440 			if( libesedb_table_definition_set_callback_catalog_definition(
441 			     *table_definition,
442 			     catalog_definition,
443 			     error ) != 1 )
444 			{
445 				libcerror_error_set(
446 				 error,
447 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
448 				 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
449 				 "%s: unable to set callback catalog definition in table definition.",
450 				 function );
451 
452 				goto on_error;
453 			}
454 			catalog_definition = NULL;
455 
456 			break;
457 
458 		default:
459 #if defined( HAVE_DEBUG_OUTPUT )
460 			if( libcnotify_verbose != 0 )
461 			{
462 				libcnotify_printf(
463 				 "%s: unsupported catalog definition type: %" PRIu16 ".\n",
464 				 function,
465 				 catalog_definition->type );
466 			}
467 #endif
468 			if( libesedb_catalog_definition_free(
469 			     &catalog_definition,
470 			     error ) != 1 )
471 			{
472 				libcerror_error_set(
473 				 error,
474 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
475 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
476 				 "%s: unable to free catalog definition.",
477 				 function );
478 
479 				goto on_error;
480 			}
481 			catalog_definition = NULL;
482 
483 			break;
484 	}
485 	return( 1 );
486 
487 on_error:
488 	if( catalog_definition != NULL )
489 	{
490 		libesedb_catalog_definition_free(
491 		 &catalog_definition,
492 		 NULL );
493 	}
494 	return( -1 );
495 }
496 
497 /* Reads the catalog values from a leaf page
498  * Returns 1 if successful or -1 on error
499  */
libesedb_catalog_read_values_from_leaf_page(libesedb_catalog_t * catalog,libesedb_page_t * page,libesedb_table_definition_t ** table_definition,libcerror_error_t ** error)500 int libesedb_catalog_read_values_from_leaf_page(
501      libesedb_catalog_t *catalog,
502      libesedb_page_t *page,
503      libesedb_table_definition_t **table_definition,
504      libcerror_error_t **error )
505 {
506 	libesedb_page_tree_value_t *page_tree_value = NULL;
507 	libesedb_page_value_t *page_value           = NULL;
508 	static char *function                       = "libesedb_catalog_read_values_from_leaf_page";
509 	uint32_t page_flags                         = 0;
510 	uint16_t number_of_page_values              = 0;
511 	uint16_t page_value_index                   = 0;
512 
513 	if( catalog == NULL )
514 	{
515 		libcerror_error_set(
516 		 error,
517 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
518 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
519 		 "%s: invalid catalog.",
520 		 function );
521 
522 		return( -1 );
523 	}
524 	if( libesedb_page_get_flags(
525 	     page,
526 	     &page_flags,
527 	     error ) != 1 )
528 	{
529 		libcerror_error_set(
530 		 error,
531 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
532 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
533 		 "%s: unable to retrieve page flags.",
534 		 function );
535 
536 		goto on_error;
537 	}
538 	if( ( page_flags & LIBESEDB_PAGE_FLAG_IS_LEAF ) == 0 )
539 	{
540 		libcerror_error_set(
541 		 error,
542 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
543 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
544 		 "%s: unsupported page - not a leaf page.",
545 		 function );
546 
547 		goto on_error;
548 	}
549 	if( libesedb_page_get_number_of_values(
550 	     page,
551 	     &number_of_page_values,
552 	     error ) != 1 )
553 	{
554 		libcerror_error_set(
555 		 error,
556 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
557 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
558 		 "%s: unable to retrieve number of page values.",
559 		 function );
560 
561 		goto on_error;
562 	}
563 	for( page_value_index = 1;
564 	     page_value_index < number_of_page_values;
565 	     page_value_index++ )
566 	{
567 		if( libesedb_page_get_value_by_index(
568 		     page,
569 		     page_value_index,
570 		     &page_value,
571 		     error ) != 1 )
572 		{
573 			libcerror_error_set(
574 			 error,
575 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
576 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
577 			 "%s: unable to retrieve page value: %" PRIu16 ".",
578 			 function,
579 			 page_value_index );
580 
581 			goto on_error;
582 		}
583 		if( page_value == NULL )
584 		{
585 			libcerror_error_set(
586 			 error,
587 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
588 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
589 			 "%s: missing page value: %" PRIu16 ".",
590 			 function,
591 			 page_value_index );
592 
593 			goto on_error;
594 		}
595 #if defined( HAVE_DEBUG_OUTPUT )
596 		if( libcnotify_verbose != 0 )
597 		{
598 			libcnotify_printf(
599 			 "%s: page value: %03" PRIu16 " page tag flags\t\t: 0x%02" PRIx8 "",
600 			 function,
601 			 page_value_index,
602 			 page_value->flags );
603 			libesedb_debug_print_page_tag_flags(
604 			 page_value->flags );
605 			libcnotify_printf(
606 			 "\n" );
607 		}
608 #endif
609 		if( ( page_value->flags & LIBESEDB_PAGE_TAG_FLAG_IS_DEFUNCT ) != 0 )
610 		{
611 			continue;
612 		}
613 		if( libesedb_page_tree_value_initialize(
614 		     &page_tree_value,
615 		     error ) != 1 )
616 		{
617 			libcerror_error_set(
618 			 error,
619 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
620 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
621 			 "%s: unable to create page tree value.",
622 			 function );
623 
624 			goto on_error;
625 		}
626 		if( libesedb_page_tree_value_read_data(
627 		     page_tree_value,
628 		     page_value->data,
629 		     (size_t) page_value->size,
630 		     page_value->flags,
631 		     error ) != 1 )
632 		{
633 			libcerror_error_set(
634 			 error,
635 			 LIBCERROR_ERROR_DOMAIN_IO,
636 			 LIBCERROR_IO_ERROR_READ_FAILED,
637 			 "%s: unable to read page tree value: %" PRIu16 ".",
638 			 function,
639 			 page_value_index );
640 
641 			goto on_error;
642 		}
643 		if( libesedb_catalog_read_value_data(
644 		     catalog,
645 		     page_tree_value->data,
646 		     page_tree_value->data_size,
647 		     table_definition,
648 		     error ) != 1 )
649 		{
650 			libcerror_error_set(
651 			 error,
652 			 LIBCERROR_ERROR_DOMAIN_IO,
653 			 LIBCERROR_IO_ERROR_READ_FAILED,
654 			 "%s: unable to read catalog value.",
655 			 function );
656 
657 			goto on_error;
658 		}
659 		if( libesedb_page_tree_value_free(
660 		     &page_tree_value,
661 		     error ) != 1 )
662 		{
663 			libcerror_error_set(
664 			 error,
665 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
666 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
667 			 "%s: unable to free page tree value.",
668 			 function );
669 
670 			goto on_error;
671 		}
672 	}
673 	return( 1 );
674 
675 on_error:
676 	if( page_tree_value != NULL )
677 	{
678 		libesedb_page_tree_value_free(
679 		 &page_tree_value,
680 		 NULL );
681 	}
682 	return( -1 );
683 }
684 
685 /* Reads the catalog
686  * Returns 1 if successful or -1 on error
687  */
libesedb_catalog_read_file_io_handle(libesedb_catalog_t * catalog,libbfio_handle_t * file_io_handle,libcerror_error_t ** error)688 int libesedb_catalog_read_file_io_handle(
689      libesedb_catalog_t *catalog,
690      libbfio_handle_t *file_io_handle,
691      libcerror_error_t **error )
692 {
693 	libesedb_page_t *page                         = NULL;
694 	libesedb_table_definition_t *table_definition = NULL;
695 	static char *function                         = "libesedb_catalog_read_file_io_handle";
696 	uint32_t leaf_page_number                     = 0;
697 	int recursion_depth                           = 0;
698 
699 	if( catalog == NULL )
700 	{
701 		libcerror_error_set(
702 		 error,
703 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
704 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
705 		 "%s: invalid catalog.",
706 		 function );
707 
708 		return( -1 );
709 	}
710 	if( catalog->page_tree == NULL )
711 	{
712 		libcerror_error_set(
713 		 error,
714 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
715 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
716 		 "%s: invalid catalog - missing page tree.",
717 		 function );
718 
719 		return( -1 );
720 	}
721 	if( libesedb_page_tree_get_get_first_leaf_page_number(
722 	     catalog->page_tree,
723 	     file_io_handle,
724 	     &leaf_page_number,
725 	     error ) != 1 )
726 	{
727 		libcerror_error_set(
728 		 error,
729 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
730 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
731 		 "%s: unable to retrieve first leaf page number from page tree.",
732 		 function );
733 
734 		return( -1 );
735 	}
736 	while( leaf_page_number != 0 )
737 	{
738 		if( recursion_depth > LIBESEDB_MAXIMUM_LEAF_PAGE_RECURSION_DEPTH )
739 		{
740 			libcerror_error_set(
741 			 error,
742 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
743 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
744 			 "%s: invalid recursion depth value out of bounds.",
745 			 function );
746 
747 			return( -1 );
748 		}
749 #if ( SIZEOF_INT <= 4 )
750 		if( leaf_page_number > (uint32_t) INT_MAX )
751 #else
752 		if( leaf_page_number > (unsigned int) INT_MAX )
753 #endif
754 		{
755 			libcerror_error_set(
756 			 error,
757 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
758 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
759 			 "%s: invalid leaf page number value out of bounds.",
760 			 function );
761 
762 			return( -1 );
763 		}
764 		if( libfdata_vector_get_element_value_by_index(
765 		     catalog->page_tree->pages_vector,
766 		     (intptr_t *) file_io_handle,
767 		     (libfdata_cache_t *) catalog->page_tree->pages_cache,
768 		     (int) leaf_page_number - 1,
769 		     (intptr_t **) &page,
770 		     0,
771 		     error ) != 1 )
772 		{
773 			libcerror_error_set(
774 			 error,
775 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
776 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
777 			 "%s: unable to retrieve page: %" PRIu32 ".",
778 			 function,
779 			 leaf_page_number );
780 
781 			return( -1 );
782 		}
783 		if( libesedb_catalog_read_values_from_leaf_page(
784 		     catalog,
785 		     page,
786 		     &table_definition,
787 		     error ) != 1 )
788 		{
789 			libcerror_error_set(
790 			 error,
791 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
792 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
793 			 "%s: unable to read values from page: %" PRIu32 ".",
794 			 function,
795 			 leaf_page_number );
796 
797 			return( -1 );
798 		}
799 		if( libesedb_page_get_next_page_number(
800 		     page,
801 		     &leaf_page_number,
802 		     error ) != 1 )
803 		{
804 			libcerror_error_set(
805 			 error,
806 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
807 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
808 			 "%s: unable to retrieve next page number from page: %" PRIu32 ".",
809 			 function,
810 			 leaf_page_number );
811 
812 			return( -1 );
813 		}
814 		recursion_depth++;
815 	}
816 	return( 1 );
817 }
818 
819 /* Retrieves the number of table definitions
820  * Returns 1 if successful or -1 on error
821  */
libesedb_catalog_get_number_of_table_definitions(libesedb_catalog_t * catalog,int * number_of_table_definitions,libcerror_error_t ** error)822 int libesedb_catalog_get_number_of_table_definitions(
823      libesedb_catalog_t *catalog,
824      int *number_of_table_definitions,
825      libcerror_error_t **error )
826 {
827 	static char *function = "libesedb_catalog_get_number_of_table_definitions";
828 
829 	if( catalog == NULL )
830 	{
831 		libcerror_error_set(
832 		 error,
833 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
834 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
835 		 "%s: invalid catalog.",
836 		 function );
837 
838 		return( -1 );
839 	}
840 	if( libcdata_array_get_number_of_entries(
841 	     catalog->table_definition_array,
842 	     number_of_table_definitions,
843 	     error ) != 1 )
844 	{
845 		libcerror_error_set(
846 		 error,
847 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
848 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
849 		 "%s: unable to retrieve number of entries from table definition array.",
850 		 function );
851 
852 		return( -1 );
853 	}
854 	return( 1 );
855 }
856 
857 /* Retrieves the table definition for the specific index
858  * Returns 1 if successful or -1 on error
859  */
libesedb_catalog_get_table_definition_by_index(libesedb_catalog_t * catalog,int table_definition_index,libesedb_table_definition_t ** table_definition,libcerror_error_t ** error)860 int libesedb_catalog_get_table_definition_by_index(
861      libesedb_catalog_t *catalog,
862      int table_definition_index,
863      libesedb_table_definition_t **table_definition,
864      libcerror_error_t **error )
865 {
866 	static char *function = "libesedb_catalog_get_table_definition_by_index";
867 
868 	if( catalog == NULL )
869 	{
870 		libcerror_error_set(
871 		 error,
872 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
873 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
874 		 "%s: invalid catalog.",
875 		 function );
876 
877 		return( -1 );
878 	}
879 	if( libcdata_array_get_entry_by_index(
880 	     catalog->table_definition_array,
881 	     table_definition_index,
882 	     (intptr_t **) table_definition,
883 	     error ) != 1 )
884 	{
885 		libcerror_error_set(
886 		 error,
887 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
888 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
889 		 "%s: unable to retrieve entry: %d from table definition array.",
890 		 function,
891 		 table_definition_index );
892 
893 		return( -1 );
894 	}
895 	return( 1 );
896 }
897 
898 /* Retrieves the table definition for the specific name
899  * Returns 1 if successful, 0 if no corresponding table definition was found or -1 on error
900  */
libesedb_catalog_get_table_definition_by_name(libesedb_catalog_t * catalog,const uint8_t * table_name,size_t table_name_size,libesedb_table_definition_t ** table_definition,libcerror_error_t ** error)901 int libesedb_catalog_get_table_definition_by_name(
902      libesedb_catalog_t *catalog,
903      const uint8_t *table_name,
904      size_t table_name_size,
905      libesedb_table_definition_t **table_definition,
906      libcerror_error_t **error )
907 {
908 	libesedb_table_definition_t *safe_table_definition = NULL;
909 	static char *function                              = "libesedb_catalog_get_table_definition_by_name";
910 	int entry_index                                    = 0;
911 	int number_of_entries                              = 0;
912 	int result                                         = 0;
913 
914 	if( catalog == NULL )
915 	{
916 		libcerror_error_set(
917 		 error,
918 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
919 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
920 		 "%s: invalid catalog.",
921 		 function );
922 
923 		return( -1 );
924 	}
925 	if( table_name == NULL )
926 	{
927 		libcerror_error_set(
928 		 error,
929 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
930 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
931 		 "%s: invalid table name.",
932 		 function );
933 
934 		return( -1 );
935 	}
936 	if( ( table_name_size == 0 )
937 	 || ( table_name_size > (size_t) SSIZE_MAX ) )
938 	{
939 		libcerror_error_set(
940 		 error,
941 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
942 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
943 		 "%s: invalid table name size value exceeds maximum.",
944 		 function );
945 
946 		return( -1 );
947 	}
948 	if( table_definition == NULL )
949 	{
950 		libcerror_error_set(
951 		 error,
952 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
953 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
954 		 "%s: invalid table definition.",
955 		 function );
956 
957 		return( -1 );
958 	}
959 	*table_definition = NULL;
960 
961 	if( libcdata_array_get_number_of_entries(
962 	     catalog->table_definition_array,
963 	     &number_of_entries,
964 	     error ) != 1 )
965 	{
966 		libcerror_error_set(
967 		 error,
968 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
969 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
970 		 "%s: unable to retrieve number of entries in table definition array.",
971 		 function );
972 
973 		return( -1 );
974 	}
975 	for( entry_index = 0;
976 	     entry_index < number_of_entries;
977 	     entry_index++ )
978 	{
979 		if( libcdata_array_get_entry_by_index(
980 		     catalog->table_definition_array,
981 		     entry_index,
982 		     (intptr_t **) &safe_table_definition,
983 		     error ) != 1 )
984 		{
985 			libcerror_error_set(
986 			 error,
987 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
988 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
989 			 "%s: unable to retrieve entry: %d from table definition array.",
990 			 function,
991 			 entry_index );
992 
993 			return( -1 );
994 		}
995 		if( safe_table_definition == NULL )
996 		{
997 			libcerror_error_set(
998 			 error,
999 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1000 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1001 			 "%s: missing table definition: %d.",
1002 			 function,
1003 			 entry_index );
1004 
1005 			return( -1 );
1006 		}
1007 		result = libesedb_catalog_definition_compare_name(
1008 			  safe_table_definition->table_catalog_definition,
1009 			  table_name,
1010 			  table_name_size,
1011 			  error );
1012 
1013 		if( result == -1 )
1014 		{
1015 			libcerror_error_set(
1016 			 error,
1017 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1018 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1019 			 "%s: unable to compare table name with table catalog definition: %d name.",
1020 			 function,
1021 			 entry_index );
1022 
1023 			return( -1 );
1024 		}
1025 		else if( result == 1 )
1026 		{
1027 			break;
1028 		}
1029 	}
1030 	if( result != 0 )
1031 	{
1032 		*table_definition = safe_table_definition;
1033 	}
1034 	return( result );
1035 }
1036 
1037 /* Retrieves the table definition for the specific UTF-8 encoded name
1038  * Returns 1 if successful, 0 if no corresponding table definition was found or -1 on error
1039  */
libesedb_catalog_get_table_definition_by_utf8_name(libesedb_catalog_t * catalog,const uint8_t * utf8_string,size_t utf8_string_length,libesedb_table_definition_t ** table_definition,libcerror_error_t ** error)1040 int libesedb_catalog_get_table_definition_by_utf8_name(
1041      libesedb_catalog_t *catalog,
1042      const uint8_t *utf8_string,
1043      size_t utf8_string_length,
1044      libesedb_table_definition_t **table_definition,
1045      libcerror_error_t **error )
1046 {
1047 	libesedb_table_definition_t *safe_table_definition = NULL;
1048 	static char *function                              = "libesedb_catalog_get_table_definition_by_utf8_name";
1049 	int entry_index                                    = 0;
1050 	int number_of_entries                              = 0;
1051 	int result                                         = 0;
1052 
1053 	if( catalog == NULL )
1054 	{
1055 		libcerror_error_set(
1056 		 error,
1057 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1058 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1059 		 "%s: invalid catalog.",
1060 		 function );
1061 
1062 		return( -1 );
1063 	}
1064 	if( utf8_string == NULL )
1065 	{
1066 		libcerror_error_set(
1067 		 error,
1068 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1069 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1070 		 "%s: invalid UTF-8 string.",
1071 		 function );
1072 
1073 		return( -1 );
1074 	}
1075 	if( ( utf8_string_length == 0 )
1076 	 || ( utf8_string_length > (size_t) SSIZE_MAX ) )
1077 	{
1078 		libcerror_error_set(
1079 		 error,
1080 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1081 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1082 		 "%s: invalid UTF-8 string length value exceeds maximum.",
1083 		 function );
1084 
1085 		return( -1 );
1086 	}
1087 	if( table_definition == NULL )
1088 	{
1089 		libcerror_error_set(
1090 		 error,
1091 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1092 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1093 		 "%s: invalid table definition.",
1094 		 function );
1095 
1096 		return( -1 );
1097 	}
1098 	*table_definition = NULL;
1099 
1100 	if( libcdata_array_get_number_of_entries(
1101 	     catalog->table_definition_array,
1102 	     &number_of_entries,
1103 	     error ) != 1 )
1104 	{
1105 		libcerror_error_set(
1106 		 error,
1107 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1108 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1109 		 "%s: unable to retrieve number of entries in table definition array.",
1110 		 function );
1111 
1112 		return( -1 );
1113 	}
1114 	for( entry_index = 0;
1115 	     entry_index < number_of_entries;
1116 	     entry_index++ )
1117 	{
1118 		if( libcdata_array_get_entry_by_index(
1119 		     catalog->table_definition_array,
1120 		     entry_index,
1121 		     (intptr_t **) &safe_table_definition,
1122 		     error ) != 1 )
1123 		{
1124 			libcerror_error_set(
1125 			 error,
1126 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1127 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1128 			 "%s: unable to retrieve entry: %d from table definition array.",
1129 			 function,
1130 			 entry_index );
1131 
1132 			return( -1 );
1133 		}
1134 		if( safe_table_definition == NULL )
1135 		{
1136 			libcerror_error_set(
1137 			 error,
1138 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1139 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1140 			 "%s: missing table definition: %d.",
1141 			 function,
1142 			 entry_index );
1143 
1144 			return( -1 );
1145 		}
1146 		result = libesedb_catalog_definition_compare_name_with_utf8_string(
1147 			  safe_table_definition->table_catalog_definition,
1148 			  utf8_string,
1149 			  utf8_string_length,
1150 			  error );
1151 
1152 		if( result == -1 )
1153 		{
1154 			libcerror_error_set(
1155 			 error,
1156 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1157 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1158 			 "%s: unable to compare UTF-8 string with table catalog definition: %d name.",
1159 			 function,
1160 			 entry_index );
1161 
1162 			return( -1 );
1163 		}
1164 		else if( result == LIBUNA_COMPARE_EQUAL )
1165 		{
1166 			result = 1;
1167 
1168 			break;
1169 		}
1170 	}
1171 	if( result != 0 )
1172 	{
1173 		*table_definition = safe_table_definition;
1174 	}
1175 	return( result );
1176 }
1177 
1178 /* Retrieves the table definition for the specific UTF-16 encoded name
1179  * Returns 1 if successful, 0 if no corresponding table definition was found or -1 on error
1180  */
libesedb_catalog_get_table_definition_by_utf16_name(libesedb_catalog_t * catalog,const uint16_t * utf16_string,size_t utf16_string_length,libesedb_table_definition_t ** table_definition,libcerror_error_t ** error)1181 int libesedb_catalog_get_table_definition_by_utf16_name(
1182      libesedb_catalog_t *catalog,
1183      const uint16_t *utf16_string,
1184      size_t utf16_string_length,
1185      libesedb_table_definition_t **table_definition,
1186      libcerror_error_t **error )
1187 {
1188 	libesedb_table_definition_t *safe_table_definition = NULL;
1189 	static char *function                              = "libesedb_catalog_get_table_definition_by_utf16_name";
1190 	int entry_index                                    = 0;
1191 	int number_of_entries                              = 0;
1192 	int result                                         = 0;
1193 
1194 	if( catalog == NULL )
1195 	{
1196 		libcerror_error_set(
1197 		 error,
1198 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1199 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1200 		 "%s: invalid catalog.",
1201 		 function );
1202 
1203 		return( -1 );
1204 	}
1205 	if( utf16_string == NULL )
1206 	{
1207 		libcerror_error_set(
1208 		 error,
1209 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1210 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1211 		 "%s: invalid UTF-16 string.",
1212 		 function );
1213 
1214 		return( -1 );
1215 	}
1216 	if( ( utf16_string_length == 0 )
1217 	 || ( utf16_string_length > (size_t) SSIZE_MAX ) )
1218 	{
1219 		libcerror_error_set(
1220 		 error,
1221 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1222 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1223 		 "%s: invalid UTF-16 string length value exceeds maximum.",
1224 		 function );
1225 
1226 		return( -1 );
1227 	}
1228 	if( table_definition == NULL )
1229 	{
1230 		libcerror_error_set(
1231 		 error,
1232 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1233 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1234 		 "%s: invalid table definition.",
1235 		 function );
1236 
1237 		return( -1 );
1238 	}
1239 	*table_definition = NULL;
1240 
1241 	if( libcdata_array_get_number_of_entries(
1242 	     catalog->table_definition_array,
1243 	     &number_of_entries,
1244 	     error ) != 1 )
1245 	{
1246 		libcerror_error_set(
1247 		 error,
1248 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1249 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1250 		 "%s: unable to retrieve number of entries in table definition array.",
1251 		 function );
1252 
1253 		return( -1 );
1254 	}
1255 	for( entry_index = 0;
1256 	     entry_index < number_of_entries;
1257 	     entry_index++ )
1258 	{
1259 		if( libcdata_array_get_entry_by_index(
1260 		     catalog->table_definition_array,
1261 		     entry_index,
1262 		     (intptr_t **) &safe_table_definition,
1263 		     error ) != 1 )
1264 		{
1265 			libcerror_error_set(
1266 			 error,
1267 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1268 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1269 			 "%s: unable to retrieve entry: %d from table definition array.",
1270 			 function,
1271 			 entry_index );
1272 
1273 			return( -1 );
1274 		}
1275 		if( safe_table_definition == NULL )
1276 		{
1277 			libcerror_error_set(
1278 			 error,
1279 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1280 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1281 			 "%s: missing table definition: %d.",
1282 			 function,
1283 			 entry_index );
1284 
1285 			return( -1 );
1286 		}
1287 		result = libesedb_catalog_definition_compare_name_with_utf16_string(
1288 			  safe_table_definition->table_catalog_definition,
1289 			  utf16_string,
1290 			  utf16_string_length,
1291 			  error );
1292 
1293 		if( result == -1 )
1294 		{
1295 			libcerror_error_set(
1296 			 error,
1297 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1298 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1299 			 "%s: unable to compare UTF-16 string with table catalog definition: %d name.",
1300 			 function,
1301 			 entry_index );
1302 
1303 			return( -1 );
1304 		}
1305 		else if( result == LIBUNA_COMPARE_EQUAL )
1306 		{
1307 			result = 1;
1308 
1309 			break;
1310 		}
1311 	}
1312 	if( result != 0 )
1313 	{
1314 		*table_definition = safe_table_definition;
1315 	}
1316 	return( result );
1317 }
1318 
1319