1 /*
2  * File functions
3  *
4  * Copyright (C) 2011-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 "libevtx_chunks_table.h"
29 #include "libevtx_codepage.h"
30 #include "libevtx_chunk.h"
31 #include "libevtx_debug.h"
32 #include "libevtx_definitions.h"
33 #include "libevtx_i18n.h"
34 #include "libevtx_io_handle.h"
35 #include "libevtx_file.h"
36 #include "libevtx_libbfio.h"
37 #include "libevtx_libcerror.h"
38 #include "libevtx_libcnotify.h"
39 #include "libevtx_libfcache.h"
40 #include "libevtx_libfdata.h"
41 #include "libevtx_record.h"
42 #include "libevtx_record_values.h"
43 
44 /* Creates a file
45  * Make sure the value file is referencing, is set to NULL
46  * Returns 1 if successful or -1 on error
47  */
libevtx_file_initialize(libevtx_file_t ** file,libcerror_error_t ** error)48 int libevtx_file_initialize(
49      libevtx_file_t **file,
50      libcerror_error_t **error )
51 {
52 	libevtx_internal_file_t *internal_file = NULL;
53 	static char *function                  = "libevtx_file_initialize";
54 
55 	if( file == NULL )
56 	{
57 		libcerror_error_set(
58 		 error,
59 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
60 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
61 		 "%s: invalid file.",
62 		 function );
63 
64 		return( -1 );
65 	}
66 	if( *file != NULL )
67 	{
68 		libcerror_error_set(
69 		 error,
70 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
71 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
72 		 "%s: invalid file value already set.",
73 		 function );
74 
75 		return( -1 );
76 	}
77 	internal_file = memory_allocate_structure(
78 	                 libevtx_internal_file_t );
79 
80 	if( internal_file == NULL )
81 	{
82 		libcerror_error_set(
83 		 error,
84 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
85 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
86 		 "%s: unable to create file.",
87 		 function );
88 
89 		goto on_error;
90 	}
91 	if( memory_set(
92 	     internal_file,
93 	     0,
94 	     sizeof( libevtx_internal_file_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 file.",
101 		 function );
102 
103 		memory_free(
104 		 internal_file );
105 
106 		return( -1 );
107 	}
108 	if( libevtx_io_handle_initialize(
109 	     &( internal_file->io_handle ),
110 	     error ) != 1 )
111 	{
112 		libcerror_error_set(
113 		 error,
114 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
115 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
116 		 "%s: unable to create IO handle.",
117 		 function );
118 
119 		goto on_error;
120 	}
121 	if( libevtx_i18n_initialize(
122 	     error ) != 1 )
123 	{
124 		libcerror_error_set(
125 		 error,
126 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
127 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
128 		 "%s: unable to initalize internationalization (i18n).",
129 		 function );
130 
131 		goto on_error;
132 	}
133 	*file = (libevtx_file_t *) internal_file;
134 
135 	return( 1 );
136 
137 on_error:
138 	if( internal_file != NULL )
139 	{
140 		if( internal_file->io_handle != NULL )
141 		{
142 			libevtx_io_handle_free(
143 			 &( internal_file->io_handle ),
144 			 NULL );
145 		}
146 		memory_free(
147 		 internal_file );
148 	}
149 	return( -1 );
150 }
151 
152 /* Frees a file
153  * Returns 1 if successful or -1 on error
154  */
libevtx_file_free(libevtx_file_t ** file,libcerror_error_t ** error)155 int libevtx_file_free(
156      libevtx_file_t **file,
157      libcerror_error_t **error )
158 {
159 	libevtx_internal_file_t *internal_file = NULL;
160 	static char *function                  = "libevtx_file_free";
161 	int result                             = 1;
162 
163 	if( file == NULL )
164 	{
165 		libcerror_error_set(
166 		 error,
167 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
168 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
169 		 "%s: invalid file.",
170 		 function );
171 
172 		return( -1 );
173 	}
174 	if( *file != NULL )
175 	{
176 		internal_file = (libevtx_internal_file_t *) *file;
177 
178 		if( internal_file->file_io_handle != NULL )
179 		{
180 			if( libevtx_file_close(
181 			     *file,
182 			     error ) != 0 )
183 			{
184 				libcerror_error_set(
185 				 error,
186 				 LIBCERROR_ERROR_DOMAIN_IO,
187 				 LIBCERROR_IO_ERROR_CLOSE_FAILED,
188 				 "%s: unable to close file.",
189 				 function );
190 
191 				result = -1;
192 			}
193 		}
194 		*file = NULL;
195 
196 		if( libevtx_io_handle_free(
197 		     &( internal_file->io_handle ),
198 		     error ) != 1 )
199 		{
200 			libcerror_error_set(
201 			 error,
202 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
203 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
204 			 "%s: unable to free IO handle.",
205 			 function );
206 
207 			result = -1;
208 		}
209 		memory_free(
210 		 internal_file );
211 	}
212 	return( result );
213 }
214 
215 /* Signals a file to abort its current activity
216  * Returns 1 if successful or -1 on error
217  */
libevtx_file_signal_abort(libevtx_file_t * file,libcerror_error_t ** error)218 int libevtx_file_signal_abort(
219      libevtx_file_t *file,
220      libcerror_error_t **error )
221 {
222 	libevtx_internal_file_t *internal_file = NULL;
223 	static char *function                  = "libevtx_file_signal_abort";
224 
225 	if( file == NULL )
226 	{
227 		libcerror_error_set(
228 		 error,
229 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
230 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
231 		 "%s: invalid file.",
232 		 function );
233 
234 		return( -1 );
235 	}
236 	internal_file = (libevtx_internal_file_t *) file;
237 
238 	if( internal_file->io_handle == NULL )
239 	{
240 		libcerror_error_set(
241 		 error,
242 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
243 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
244 		 "%s: invalid file - missing IO handle.",
245 		 function );
246 
247 		return( -1 );
248 	}
249 	internal_file->io_handle->abort = 1;
250 
251 	return( 1 );
252 }
253 
254 /* Opens a file
255  * Returns 1 if successful or -1 on error
256  */
libevtx_file_open(libevtx_file_t * file,const char * filename,int access_flags,libcerror_error_t ** error)257 int libevtx_file_open(
258      libevtx_file_t *file,
259      const char *filename,
260      int access_flags,
261      libcerror_error_t **error )
262 {
263 	libbfio_handle_t *file_io_handle       = NULL;
264 	libevtx_internal_file_t *internal_file = NULL;
265 	static char *function                  = "libevtx_file_open";
266 	size_t filename_length                 = 0;
267 
268 	if( file == NULL )
269 	{
270 		libcerror_error_set(
271 		 error,
272 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
273 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
274 		 "%s: invalid file.",
275 		 function );
276 
277 		return( -1 );
278 	}
279 	internal_file = (libevtx_internal_file_t *) file;
280 
281 	if( filename == NULL )
282 	{
283 		libcerror_error_set(
284 		 error,
285 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
286 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
287 		 "%s: invalid filename.",
288 		 function );
289 
290 		return( -1 );
291 	}
292 	if( ( ( access_flags & LIBEVTX_ACCESS_FLAG_READ ) == 0 )
293 	 && ( ( access_flags & LIBEVTX_ACCESS_FLAG_WRITE ) == 0 ) )
294 	{
295 		libcerror_error_set(
296 		 error,
297 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
298 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
299 		 "%s: unsupported access flags.",
300 		 function );
301 
302 		return( -1 );
303 	}
304 	if( ( access_flags & LIBEVTX_ACCESS_FLAG_WRITE ) != 0 )
305 	{
306 		libcerror_error_set(
307 		 error,
308 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
309 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
310 		 "%s: write access currently not supported.",
311 		 function );
312 
313 		return( -1 );
314 	}
315 	if( libbfio_file_initialize(
316 	     &file_io_handle,
317 	     error ) != 1 )
318 	{
319 		libcerror_error_set(
320 		 error,
321 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
322 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
323 		 "%s: unable to create file IO handle.",
324 		 function );
325 
326 		goto on_error;
327 	}
328 #if defined( HAVE_DEBUG_OUTPUT )
329 	if( libbfio_handle_set_track_offsets_read(
330 	     file_io_handle,
331 	     1,
332 	     error ) != 1 )
333 	{
334                 libcerror_error_set(
335                  error,
336                  LIBCERROR_ERROR_DOMAIN_RUNTIME,
337                  LIBCERROR_RUNTIME_ERROR_SET_FAILED,
338                  "%s: unable to set track offsets read in file IO handle.",
339                  function );
340 
341 		goto on_error;
342 	}
343 #endif
344 	filename_length = narrow_string_length(
345 	                   filename );
346 
347 	if( libbfio_file_set_name(
348 	     file_io_handle,
349 	     filename,
350 	     filename_length + 1,
351 	     error ) != 1 )
352 	{
353                 libcerror_error_set(
354                  error,
355                  LIBCERROR_ERROR_DOMAIN_RUNTIME,
356                  LIBCERROR_RUNTIME_ERROR_SET_FAILED,
357                  "%s: unable to set filename in file IO handle.",
358                  function );
359 
360 		goto on_error;
361 	}
362 	if( libevtx_file_open_file_io_handle(
363 	     file,
364 	     file_io_handle,
365 	     access_flags,
366 	     error ) != 1 )
367 	{
368 		libcerror_error_set(
369 		 error,
370 		 LIBCERROR_ERROR_DOMAIN_IO,
371 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
372 		 "%s: unable to open file: %s.",
373 		 function,
374 		 filename );
375 
376 		goto on_error;
377 	}
378 	internal_file->file_io_handle_created_in_library = 1;
379 
380 	return( 1 );
381 
382 on_error:
383 	if( file_io_handle != NULL )
384 	{
385 		libbfio_handle_free(
386 		 &file_io_handle,
387 		 NULL );
388 	}
389 	return( -1 );
390 }
391 
392 #if defined( HAVE_WIDE_CHARACTER_TYPE )
393 
394 /* Opens a file
395  * Returns 1 if successful or -1 on error
396  */
libevtx_file_open_wide(libevtx_file_t * file,const wchar_t * filename,int access_flags,libcerror_error_t ** error)397 int libevtx_file_open_wide(
398      libevtx_file_t *file,
399      const wchar_t *filename,
400      int access_flags,
401      libcerror_error_t **error )
402 {
403 	libbfio_handle_t *file_io_handle       = NULL;
404 	libevtx_internal_file_t *internal_file = NULL;
405 	static char *function                  = "libevtx_file_open_wide";
406 	size_t filename_length                 = 0;
407 
408 	if( file == NULL )
409 	{
410 		libcerror_error_set(
411 		 error,
412 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
413 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
414 		 "%s: invalid file.",
415 		 function );
416 
417 		return( -1 );
418 	}
419 	internal_file = (libevtx_internal_file_t *) file;
420 
421 	if( filename == NULL )
422 	{
423 		libcerror_error_set(
424 		 error,
425 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
426 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
427 		 "%s: invalid filename.",
428 		 function );
429 
430 		return( -1 );
431 	}
432 	if( ( ( access_flags & LIBEVTX_ACCESS_FLAG_READ ) == 0 )
433 	 && ( ( access_flags & LIBEVTX_ACCESS_FLAG_WRITE ) == 0 ) )
434 	{
435 		libcerror_error_set(
436 		 error,
437 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
438 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
439 		 "%s: unsupported access flags.",
440 		 function );
441 
442 		return( -1 );
443 	}
444 	if( ( access_flags & LIBEVTX_ACCESS_FLAG_WRITE ) != 0 )
445 	{
446 		libcerror_error_set(
447 		 error,
448 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
449 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
450 		 "%s: write access currently not supported.",
451 		 function );
452 
453 		return( -1 );
454 	}
455 	if( libbfio_file_initialize(
456 	     &file_io_handle,
457 	     error ) != 1 )
458 	{
459 		libcerror_error_set(
460 		 error,
461 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
462 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
463 		 "%s: unable to create file IO handle.",
464 		 function );
465 
466 		goto on_error;
467 	}
468 #if defined( HAVE_DEBUG_OUTPUT )
469 	if( libbfio_handle_set_track_offsets_read(
470 	     file_io_handle,
471 	     1,
472 	     error ) != 1 )
473 	{
474                 libcerror_error_set(
475                  error,
476                  LIBCERROR_ERROR_DOMAIN_RUNTIME,
477                  LIBCERROR_RUNTIME_ERROR_SET_FAILED,
478                  "%s: unable to set track offsets read in file IO handle.",
479                  function );
480 
481 		goto on_error;
482 	}
483 #endif
484 	filename_length = wide_string_length(
485 	                   filename );
486 
487 	if( libbfio_file_set_name_wide(
488 	     file_io_handle,
489 	     filename,
490 	     filename_length + 1,
491 	     error ) != 1 )
492 	{
493                 libcerror_error_set(
494                  error,
495                  LIBCERROR_ERROR_DOMAIN_RUNTIME,
496                  LIBCERROR_RUNTIME_ERROR_SET_FAILED,
497                  "%s: unable to set filename in file IO handle.",
498                  function );
499 
500 		goto on_error;
501 	}
502 	if( libevtx_file_open_file_io_handle(
503 	     file,
504 	     file_io_handle,
505 	     access_flags,
506 	     error ) != 1 )
507 	{
508 		libcerror_error_set(
509 		 error,
510 		 LIBCERROR_ERROR_DOMAIN_IO,
511 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
512 		 "%s: unable to open file: %ls.",
513 		 function,
514 		 filename );
515 
516 		goto on_error;
517 	}
518 	internal_file->file_io_handle_created_in_library = 1;
519 
520 	return( 1 );
521 
522 on_error:
523 	if( file_io_handle != NULL )
524 	{
525 		libbfio_handle_free(
526 		 &file_io_handle,
527 		 NULL );
528 	}
529 	return( -1 );
530 }
531 
532 #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
533 
534 /* Opens a file using a Basic File IO (bfio) handle
535  * Returns 1 if successful or -1 on error
536  */
libevtx_file_open_file_io_handle(libevtx_file_t * file,libbfio_handle_t * file_io_handle,int access_flags,libcerror_error_t ** error)537 int libevtx_file_open_file_io_handle(
538      libevtx_file_t *file,
539      libbfio_handle_t *file_io_handle,
540      int access_flags,
541      libcerror_error_t **error )
542 {
543 	libevtx_internal_file_t *internal_file = NULL;
544 	static char *function                  = "libevtx_file_open_file_io_handle";
545 	int bfio_access_flags                  = 0;
546 	int file_io_handle_is_open             = 0;
547 	int file_io_handle_opened_in_library   = 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 	internal_file = (libevtx_internal_file_t *) file;
561 
562 	if( internal_file->file_io_handle != NULL )
563 	{
564 		libcerror_error_set(
565 		 error,
566 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
567 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
568 		 "%s: invalid file - file IO handle already set.",
569 		 function );
570 
571 		return( -1 );
572 	}
573 	if( file_io_handle == NULL )
574 	{
575 		libcerror_error_set(
576 		 error,
577 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
578 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
579 		 "%s: invalid file IO handle.",
580 		 function );
581 
582 		return( -1 );
583 	}
584 	if( ( ( access_flags & LIBEVTX_ACCESS_FLAG_READ ) == 0 )
585 	 && ( ( access_flags & LIBEVTX_ACCESS_FLAG_WRITE ) == 0 ) )
586 	{
587 		libcerror_error_set(
588 		 error,
589 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
590 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
591 		 "%s: unsupported access flags.",
592 		 function );
593 
594 		return( -1 );
595 	}
596 	if( ( access_flags & LIBEVTX_ACCESS_FLAG_WRITE ) != 0 )
597 	{
598 		libcerror_error_set(
599 		 error,
600 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
601 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
602 		 "%s: write access currently not supported.",
603 		 function );
604 
605 		return( -1 );
606 	}
607 	if( ( access_flags & LIBEVTX_ACCESS_FLAG_READ ) != 0 )
608 	{
609 		bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
610 	}
611 	file_io_handle_is_open = libbfio_handle_is_open(
612 	                          file_io_handle,
613 	                          error );
614 
615 	if( file_io_handle_is_open == -1 )
616 	{
617 		libcerror_error_set(
618 		 error,
619 		 LIBCERROR_ERROR_DOMAIN_IO,
620 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
621 		 "%s: unable to open file.",
622 		 function );
623 
624 		goto on_error;
625 	}
626 	else if( file_io_handle_is_open == 0 )
627 	{
628 		if( libbfio_handle_open(
629 		     file_io_handle,
630 		     bfio_access_flags,
631 		     error ) != 1 )
632 		{
633 			libcerror_error_set(
634 			 error,
635 			 LIBCERROR_ERROR_DOMAIN_IO,
636 			 LIBCERROR_IO_ERROR_OPEN_FAILED,
637 			 "%s: unable to open file IO handle.",
638 			 function );
639 
640 			goto on_error;
641 		}
642 		file_io_handle_opened_in_library = 1;
643 	}
644 	if( libevtx_file_open_read(
645 	     internal_file,
646 	     file_io_handle,
647 	     error ) != 1 )
648 	{
649 		libcerror_error_set(
650 		 error,
651 		 LIBCERROR_ERROR_DOMAIN_IO,
652 		 LIBCERROR_IO_ERROR_READ_FAILED,
653 		 "%s: unable to read from file handle.",
654 		 function );
655 
656 		goto on_error;
657 	}
658 	internal_file->file_io_handle                   = file_io_handle;
659 	internal_file->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
660 
661 	return( 1 );
662 
663 on_error:
664 	if( file_io_handle_opened_in_library != 0 )
665 	{
666 		libbfio_handle_close(
667 		 file_io_handle,
668 		 error );
669 	}
670 	return( -1 );
671 }
672 
673 /* Closes a file
674  * Returns 0 if successful or -1 on error
675  */
libevtx_file_close(libevtx_file_t * file,libcerror_error_t ** error)676 int libevtx_file_close(
677      libevtx_file_t *file,
678      libcerror_error_t **error )
679 {
680 	libevtx_internal_file_t *internal_file = NULL;
681 	static char *function                  = "libevtx_file_close";
682 	int result                             = 0;
683 
684 	if( file == NULL )
685 	{
686 		libcerror_error_set(
687 		 error,
688 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
689 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
690 		 "%s: invalid file.",
691 		 function );
692 
693 		return( -1 );
694 	}
695 	internal_file = (libevtx_internal_file_t *) file;
696 
697 	if( internal_file->file_io_handle == NULL )
698 	{
699 		libcerror_error_set(
700 		 error,
701 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
702 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
703 		 "%s: invalid file - missing file IO handle.",
704 		 function );
705 
706 		return( -1 );
707 	}
708 #if defined( HAVE_DEBUG_OUTPUT )
709 	if( libcnotify_verbose != 0 )
710 	{
711 		if( internal_file->file_io_handle_created_in_library != 0 )
712 		{
713 			if( libevtx_debug_print_read_offsets(
714 			     internal_file->file_io_handle,
715 			     error ) != 1 )
716 			{
717 				libcerror_error_set(
718 				 error,
719 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
720 				 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
721 				 "%s: unable to print the read offsets.",
722 				 function );
723 
724 				result = -1;
725 			}
726 		}
727 	}
728 #endif
729 	if( internal_file->file_io_handle_opened_in_library != 0 )
730 	{
731 		if( libbfio_handle_close(
732 		     internal_file->file_io_handle,
733 		     error ) != 0 )
734 		{
735 			libcerror_error_set(
736 			 error,
737 			 LIBCERROR_ERROR_DOMAIN_IO,
738 			 LIBCERROR_IO_ERROR_CLOSE_FAILED,
739 			 "%s: unable to close file IO handle.",
740 			 function );
741 
742 			result = -1;
743 		}
744 		internal_file->file_io_handle_opened_in_library = 0;
745 	}
746 	if( internal_file->file_io_handle_created_in_library != 0 )
747 	{
748 		if( libbfio_handle_free(
749 		     &( internal_file->file_io_handle ),
750 		     error ) != 1 )
751 		{
752 			libcerror_error_set(
753 			 error,
754 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
755 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
756 			 "%s: unable to free file IO handle.",
757 			 function );
758 
759 			result = -1;
760 		}
761 		internal_file->file_io_handle_created_in_library = 0;
762 	}
763 	internal_file->file_io_handle = NULL;
764 
765 	if( libevtx_io_handle_clear(
766 	     internal_file->io_handle,
767 	     error ) != 1 )
768 	{
769 		libcerror_error_set(
770 		 error,
771 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
772 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
773 		 "%s: unable to clear IO handle.",
774 		 function );
775 
776 		result = -1;
777 	}
778 	if( libfdata_list_free(
779 	     &( internal_file->recovered_records_list ),
780 	     error ) != 1 )
781 	{
782 		libcerror_error_set(
783 		 error,
784 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
785 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
786 		 "%s: unable to free recovered records list.",
787 		 function );
788 
789 		result = -1;
790 	}
791 	if( libfdata_list_free(
792 	     &( internal_file->records_list ),
793 	     error ) != 1 )
794 	{
795 		libcerror_error_set(
796 		 error,
797 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
798 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
799 		 "%s: unable to free records list.",
800 		 function );
801 
802 		result = -1;
803 	}
804 	if( libfcache_cache_free(
805 	     &( internal_file->records_cache ),
806 	     error ) != 1 )
807 	{
808 		libcerror_error_set(
809 		 error,
810 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
811 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
812 		 "%s: unable to free records cache.",
813 		 function );
814 
815 		result = -1;
816 	}
817 	if( libfdata_vector_free(
818 	     &( internal_file->chunks_vector ),
819 	     error ) != 1 )
820 	{
821 		libcerror_error_set(
822 		 error,
823 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
824 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
825 		 "%s: unable to free chunks vector.",
826 		 function );
827 
828 		result = -1;
829 	}
830 	if( libfcache_cache_free(
831 	     &( internal_file->chunks_cache ),
832 	     error ) != 1 )
833 	{
834 		libcerror_error_set(
835 		 error,
836 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
837 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
838 		 "%s: unable to free chunks cache.",
839 		 function );
840 
841 		result = -1;
842 	}
843 	return( result );
844 }
845 
846 /* Opens a file for reading
847  * Returns 1 if successful or -1 on error
848  */
libevtx_file_open_read(libevtx_internal_file_t * internal_file,libbfio_handle_t * file_io_handle,libcerror_error_t ** error)849 int libevtx_file_open_read(
850      libevtx_internal_file_t *internal_file,
851      libbfio_handle_t *file_io_handle,
852      libcerror_error_t **error )
853 {
854 	libevtx_chunk_t *chunk                 = NULL;
855 	libevtx_record_values_t *record_values = NULL;
856 	libevtx_chunks_table_t *chunks_table   = NULL;
857 	static char *function                  = "libevtx_file_open_read";
858 	off64_t file_offset                    = 0;
859 	size64_t file_size                     = 0;
860 	uint16_t chunk_index                   = 0;
861 	uint16_t number_of_chunks              = 0;
862 	uint16_t number_of_records             = 0;
863 	uint16_t record_index                  = 0;
864 	int element_index                      = 0;
865 	int result                             = 0;
866 	int segment_index                      = 0;
867 
868 #if defined( HAVE_VERBOSE_OUTPUT )
869 	uint64_t previous_record_identifier    = 0;
870 #endif
871 #if defined( HAVE_DEBUG_OUTPUT )
872 	uint8_t *trailing_data                 = NULL;
873 	size_t trailing_data_size              = 0;
874 	ssize_t read_count                     = 0;
875 #endif
876 
877 	if( internal_file == NULL )
878 	{
879 		libcerror_error_set(
880 		 error,
881 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
882 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
883 		 "%s: invalid file.",
884 		 function );
885 
886 		return( -1 );
887 	}
888 	if( internal_file->io_handle == NULL )
889 	{
890 		libcerror_error_set(
891 		 error,
892 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
893 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
894 		 "%s: invalid file - missing IO handle.",
895 		 function );
896 
897 		return( -1 );
898 	}
899 	if( internal_file->chunks_vector != NULL )
900 	{
901 		libcerror_error_set(
902 		 error,
903 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
904 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
905 		 "%s: invalid file - chunks vector already set.",
906 		 function );
907 
908 		return( -1 );
909 	}
910 	if( internal_file->chunks_cache != NULL )
911 	{
912 		libcerror_error_set(
913 		 error,
914 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
915 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
916 		 "%s: invalid file - chunks cache already set.",
917 		 function );
918 
919 		return( -1 );
920 	}
921 	if( internal_file->records_list != NULL )
922 	{
923 		libcerror_error_set(
924 		 error,
925 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
926 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
927 		 "%s: invalid file - records list already set.",
928 		 function );
929 
930 		return( -1 );
931 	}
932 	if( internal_file->recovered_records_list != NULL )
933 	{
934 		libcerror_error_set(
935 		 error,
936 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
937 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
938 		 "%s: invalid file - recovered records list already set.",
939 		 function );
940 
941 		return( -1 );
942 	}
943 	if( internal_file->records_cache != NULL )
944 	{
945 		libcerror_error_set(
946 		 error,
947 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
948 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
949 		 "%s: invalid file - records cache already set.",
950 		 function );
951 
952 		return( -1 );
953 	}
954 	if( libbfio_handle_get_size(
955 	     file_io_handle,
956 	     &file_size,
957 	     error ) != 1 )
958 	{
959 		libcerror_error_set(
960 		 error,
961 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
962 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
963 		 "%s: unable to retrieve file size.",
964 		 function );
965 
966 		goto on_error;
967 	}
968 #if defined( HAVE_DEBUG_OUTPUT )
969 	if( libcnotify_verbose != 0 )
970 	{
971 		libcnotify_printf(
972 		 "Reading file header:\n" );
973 	}
974 #endif
975 	if( libevtx_io_handle_read_file_header(
976 	     internal_file->io_handle,
977 	     file_io_handle,
978 	     0,
979 	     error ) != 1 )
980 	{
981 		libcerror_error_set(
982 		 error,
983 		 LIBCERROR_ERROR_DOMAIN_IO,
984 		 LIBCERROR_IO_ERROR_READ_FAILED,
985 		 "%s: unable to read file header.",
986 		 function );
987 
988 		goto on_error;
989 	}
990 	internal_file->io_handle->chunks_data_size = file_size
991 	                                           - internal_file->io_handle->chunks_data_offset;
992 
993 /* TODO clone function ? */
994 	if( libfdata_vector_initialize(
995 	     &( internal_file->chunks_vector ),
996 	     (size64_t) internal_file->io_handle->chunk_size,
997 	     (intptr_t *) internal_file->io_handle,
998 	     NULL,
999 	     NULL,
1000 	     (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libevtx_io_handle_read_chunk,
1001 	     NULL,
1002 	     LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
1003 	     error ) != 1 )
1004 	{
1005 		libcerror_error_set(
1006 		 error,
1007 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1008 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1009 		 "%s: unable to create chunks vector.",
1010 		 function );
1011 
1012 		goto on_error;
1013 	}
1014 	if( libfdata_vector_append_segment(
1015 	     internal_file->chunks_vector,
1016 	     &segment_index,
1017 	     0,
1018 	     internal_file->io_handle->chunks_data_offset,
1019 	     internal_file->io_handle->chunks_data_size,
1020 	     0,
1021 	     error ) != 1 )
1022 	{
1023 		libcerror_error_set(
1024 		 error,
1025 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1026 		 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1027 		 "%s: unable to append segment to chunks vector.",
1028 		 function );
1029 
1030 		goto on_error;
1031 	}
1032 	if( libfcache_cache_initialize(
1033 	     &( internal_file->chunks_cache ),
1034 	     LIBEVTX_MAXIMUM_CACHE_ENTRIES_CHUNKS,
1035 	     error ) != 1 )
1036 	{
1037 		libcerror_error_set(
1038 		 error,
1039 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1040 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1041 		 "%s: unable to create chunks cache.",
1042 		 function );
1043 
1044 		goto on_error;
1045 	}
1046 #if defined( HAVE_DEBUG_OUTPUT )
1047 	if( libcnotify_verbose != 0 )
1048 	{
1049 		libcnotify_printf(
1050 		 "Reading chunks:\n" );
1051 	}
1052 #endif
1053 	if( libevtx_chunks_table_initialize(
1054 	     &chunks_table,
1055 	     internal_file->io_handle,
1056 	     internal_file->chunks_vector,
1057 	     internal_file->chunks_cache,
1058 	     error ) != 1 )
1059 	{
1060 		libcerror_error_set(
1061 		 error,
1062 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1063 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1064 		 "%s: unable to create chunks table.",
1065 		 function );
1066 
1067 		goto on_error;
1068 	}
1069 /* TODO clone function ? */
1070 	if( libfdata_list_initialize(
1071 	     &( internal_file->records_list ),
1072 	     (intptr_t *) chunks_table,
1073 	     (int (*)(intptr_t **, libcerror_error_t **)) &libevtx_chunks_table_free,
1074 	     NULL,
1075 	     (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfdata_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libevtx_chunks_table_read_record,
1076 	     NULL,
1077 	     LIBFDATA_DATA_HANDLE_FLAG_MANAGED,
1078 	     error ) != 1 )
1079 	{
1080 		libcerror_error_set(
1081 		 error,
1082 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1083 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1084 		 "%s: unable to create records list.",
1085 		 function );
1086 
1087 		goto on_error;
1088 	}
1089 	/* The chunks_table is managed by the list */
1090 
1091 	if( libfdata_list_initialize(
1092 	     &( internal_file->recovered_records_list ),
1093 	     (intptr_t *) chunks_table,
1094 	     NULL,
1095 	     NULL,
1096 	     (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfdata_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libevtx_chunks_table_read_record,
1097 	     NULL,
1098 	     LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
1099 	     error ) != 1 )
1100 	{
1101 		libcerror_error_set(
1102 		 error,
1103 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1104 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1105 		 "%s: unable to create recovered records list.",
1106 		 function );
1107 
1108 		chunks_table = NULL;
1109 
1110 		goto on_error;
1111 	}
1112 	chunks_table = NULL;
1113 
1114 	if( libfcache_cache_initialize(
1115 	     &( internal_file->records_cache ),
1116 	     LIBEVTX_MAXIMUM_CACHE_ENTRIES_RECORDS,
1117 	     error ) != 1 )
1118 	{
1119 		libcerror_error_set(
1120 		 error,
1121 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1122 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1123 		 "%s: unable to create records cache.",
1124 		 function );
1125 
1126 		goto on_error;
1127 	}
1128 	file_offset = internal_file->io_handle->chunks_data_offset;
1129 
1130 	while( ( file_offset + internal_file->io_handle->chunk_size ) <= (off64_t) file_size )
1131 	{
1132 		if( libevtx_chunk_initialize(
1133 		     &chunk,
1134 		     error ) != 1 )
1135 		{
1136 			libcerror_error_set(
1137 			 error,
1138 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1139 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1140 			 "%s: unable to create chunk: %" PRIu16 ".",
1141 			 function,
1142 			 chunk_index );
1143 
1144 			goto on_error;
1145 		}
1146 		result = libevtx_chunk_read(
1147 		          chunk,
1148 		          internal_file->io_handle,
1149 		          file_io_handle,
1150 		          file_offset,
1151 		          error );
1152 
1153 		if( result == -1 )
1154 		{
1155 			libcerror_error_set(
1156 			 error,
1157 			 LIBCERROR_ERROR_DOMAIN_IO,
1158 			 LIBCERROR_IO_ERROR_READ_FAILED,
1159 			 "%s: unable to read chunk: %" PRIu16 ".",
1160 			 function,
1161 			 chunk_index );
1162 
1163 			goto on_error;
1164 		}
1165 		else if( result == 0 )
1166 		{
1167 			if( chunk_index < internal_file->io_handle->number_of_chunks )
1168 			{
1169 #if defined( HAVE_VERBOSE_OUTPUT )
1170 				if( libcnotify_verbose != 0 )
1171 				{
1172 					libcnotify_printf(
1173 					 "%s: corruption detected in chunk: %" PRIu16 ".\n",
1174 					 function,
1175 					 chunk_index );
1176 				}
1177 #endif
1178 				internal_file->io_handle->flags |= LIBEVTX_IO_HANDLE_FLAG_IS_CORRUPTED;
1179 			}
1180 		}
1181 		else
1182 		{
1183 			if( ( chunk->flags & LIBEVTX_CHUNK_FLAG_IS_CORRUPTED ) != 0 )
1184 			{
1185 #if defined( HAVE_VERBOSE_OUTPUT )
1186 				if( libcnotify_verbose != 0 )
1187 				{
1188 					libcnotify_printf(
1189 					 "%s: corruption detected in chunk: %" PRIu16 ".\n",
1190 					 function,
1191 					 chunk_index );
1192 				}
1193 #endif
1194 				if( chunk_index < internal_file->io_handle->number_of_chunks )
1195 				{
1196 					internal_file->io_handle->flags |= LIBEVTX_IO_HANDLE_FLAG_IS_CORRUPTED;
1197 				}
1198 			}
1199 			if( ( chunk_index < internal_file->io_handle->number_of_chunks )
1200 			 || ( ( chunk->flags & LIBEVTX_CHUNK_FLAG_IS_CORRUPTED ) == 0 ) )
1201 			{
1202 				number_of_chunks++;
1203 			}
1204 			if( libevtx_chunk_get_number_of_records(
1205 			     chunk,
1206 			     &number_of_records,
1207 			     error ) != 1 )
1208 			{
1209 				libcerror_error_set(
1210 				 error,
1211 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1212 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1213 				 "%s: unable to retrieve chunk: %" PRIu16 " number of records.",
1214 				 function,
1215 				 chunk_index );
1216 
1217 				goto on_error;
1218 			}
1219 			for( record_index = 0;
1220 			     record_index < number_of_records;
1221 			     record_index++ )
1222 			{
1223 				if( libevtx_chunk_get_record(
1224 				     chunk,
1225 				     record_index,
1226 				     &record_values,
1227 				     error ) != 1 )
1228 				{
1229 					libcerror_error_set(
1230 					 error,
1231 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1232 					 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1233 					 "%s: unable to retrieve chunk: %" PRIu16 " record: %" PRIu16 ".",
1234 					 function,
1235 					 chunk_index,
1236 					 record_index );
1237 
1238 					goto on_error;
1239 				}
1240 				if( record_values == NULL )
1241 				{
1242 					libcerror_error_set(
1243 					 error,
1244 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1245 					 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1246 					 "%s: missing chunk: %" PRIu16 " record: %" PRIu16 ".",
1247 					 function,
1248 					 chunk_index,
1249 					 record_index );
1250 
1251 					goto on_error;
1252 				}
1253 				if( record_values->identifier < internal_file->io_handle->first_record_identifier )
1254 				{
1255 					internal_file->io_handle->first_record_identifier = record_values->identifier;
1256 				}
1257 				if( record_values->identifier > internal_file->io_handle->last_record_identifier )
1258 				{
1259 					internal_file->io_handle->last_record_identifier = record_values->identifier;
1260 				}
1261 #if defined( HAVE_VERBOSE_OUTPUT )
1262 				if( ( chunk_index == 0 )
1263 				 && ( record_index == 0 ) )
1264 				{
1265 					previous_record_identifier = record_values->identifier;
1266 				}
1267 				else
1268 				{
1269 					previous_record_identifier++;
1270 
1271 					if( record_values->identifier != previous_record_identifier )
1272 					{
1273 						if( libcnotify_verbose != 0 )
1274 						{
1275 							libcnotify_printf(
1276 							 "%s: detected gap in record identifier ( %" PRIu64 " != %" PRIu64 " ).\n",
1277 							 function,
1278 							 previous_record_identifier,
1279 							 record_values->identifier );
1280 						}
1281 						previous_record_identifier = record_values->identifier;
1282 					}
1283 				}
1284 #endif
1285 				/* The chunk index is stored in the element data size
1286 				 */
1287 				if( ( chunk_index < internal_file->io_handle->number_of_chunks )
1288 				 || ( ( internal_file->io_handle->file_flags & LIBEVTX_FILE_FLAG_IS_DIRTY ) != 0 ) )
1289 				{
1290 					if( libfdata_list_append_element(
1291 					     internal_file->records_list,
1292 					     &element_index,
1293 					     0,
1294 					     file_offset + record_values->chunk_data_offset,
1295 					     (size64_t) chunk_index,
1296 					     0,
1297 					     error ) != 1 )
1298 					{
1299 						libcerror_error_set(
1300 						 error,
1301 						 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1302 						 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1303 						 "%s: unable to append element to records list.",
1304 						 function );
1305 
1306 						goto on_error;
1307 					}
1308 				}
1309 				else
1310 				{
1311 					/* If the file is not dirty, records found in chunks outside the indicated
1312 					 * range are considered recovered
1313 					 */
1314 					if( libfdata_list_append_element(
1315 					     internal_file->recovered_records_list,
1316 					     &element_index,
1317 					     0,
1318 					     file_offset + record_values->chunk_data_offset,
1319 					     (size64_t) chunk_index,
1320 					     0,
1321 					     error ) != 1 )
1322 					{
1323 						libcerror_error_set(
1324 						 error,
1325 						 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1326 						 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1327 						 "%s: unable to append element to recovered records list.",
1328 						 function );
1329 
1330 						goto on_error;
1331 					}
1332 				}
1333 /* TODO cache record values ? */
1334 			}
1335 			if( libevtx_chunk_get_number_of_recovered_records(
1336 			     chunk,
1337 			     &number_of_records,
1338 			     error ) != 1 )
1339 			{
1340 				libcerror_error_set(
1341 				 error,
1342 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1343 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1344 				 "%s: unable to retrieve chunk: %" PRIu16 " number of recovered records.",
1345 				 function,
1346 				 chunk_index );
1347 
1348 				goto on_error;
1349 			}
1350 			for( record_index = 0;
1351 			     record_index < number_of_records;
1352 			     record_index++ )
1353 			{
1354 				if( libevtx_chunk_get_recovered_record(
1355 				     chunk,
1356 				     record_index,
1357 				     &record_values,
1358 				     error ) != 1 )
1359 				{
1360 					libcerror_error_set(
1361 					 error,
1362 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1363 					 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1364 					 "%s: unable to retrieve chunk: %" PRIu16 " recovered record: %" PRIu16 ".",
1365 					 function,
1366 					 chunk_index,
1367 					 record_index );
1368 
1369 					goto on_error;
1370 				}
1371 				if( record_values == NULL )
1372 				{
1373 					libcerror_error_set(
1374 					 error,
1375 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1376 					 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1377 					 "%s: missing chunk: %" PRIu16 " recovered record: %" PRIu16 ".",
1378 					 function,
1379 					 chunk_index,
1380 					 record_index );
1381 
1382 					goto on_error;
1383 				}
1384 /* TODO check for and remove duplicate identifiers ? */
1385 				/* The chunk index is stored in the element data size
1386 				 */
1387 				if( libfdata_list_append_element(
1388 				     internal_file->recovered_records_list,
1389 				     &element_index,
1390 				     0,
1391 				     file_offset + record_values->chunk_data_offset,
1392 				     (size64_t) chunk_index,
1393 				     0,
1394 				     error ) != 1 )
1395 				{
1396 					libcerror_error_set(
1397 					 error,
1398 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1399 					 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1400 					 "%s: unable to append element to recovered records list.",
1401 					 function );
1402 
1403 					goto on_error;
1404 				}
1405 			}
1406 		}
1407 		file_offset += chunk->data_size;
1408 
1409 		if( libevtx_chunk_free(
1410 		     &chunk,
1411 		     error ) != 1 )
1412 		{
1413 			libcerror_error_set(
1414 			 error,
1415 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1416 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1417 			 "%s: unable to free chunk: %" PRIu16 ".",
1418 			 function,
1419 			 chunk_index );
1420 
1421 			goto on_error;
1422 		}
1423 		chunk_index++;
1424 	}
1425 	internal_file->io_handle->chunks_data_size = file_offset
1426 	                                           - internal_file->io_handle->chunks_data_offset;
1427 
1428 	if( number_of_chunks != internal_file->io_handle->number_of_chunks )
1429 	{
1430 #if defined( HAVE_VERBOSE_OUTPUT )
1431 		if( libcnotify_verbose != 0 )
1432 		{
1433 			libcnotify_printf(
1434 			 "%s: mismatch in number of chunks ( %" PRIu16 " != %" PRIu16 " ).\n",
1435 			 function,
1436 			 internal_file->io_handle->number_of_chunks,
1437 			 chunk_index );
1438 		}
1439 #endif
1440 		internal_file->io_handle->flags |= LIBEVTX_IO_HANDLE_FLAG_IS_CORRUPTED;
1441 	}
1442 #if defined( HAVE_DEBUG_OUTPUT )
1443 	if( libcnotify_verbose != 0 )
1444 	{
1445 		if( file_offset < (off64_t) file_size )
1446 		{
1447 			trailing_data_size = (size_t) ( file_size - file_offset );
1448 
1449 			if( trailing_data_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE )
1450 			{
1451 				libcerror_error_set(
1452 				 error,
1453 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1454 				 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1455 				 "%s: invalid trailing data size value exceeds maximum allocation size.",
1456 				 function );
1457 
1458 				goto on_error;
1459 			}
1460 			trailing_data = (uint8_t *) memory_allocate(
1461 			                             sizeof( uint8_t ) * trailing_data_size );
1462 
1463 			if( trailing_data == NULL )
1464 			{
1465 				libcerror_error_set(
1466 				 error,
1467 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
1468 				 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1469 				 "%s: unable to create trailing data.",
1470 				 function );
1471 
1472 				goto on_error;
1473 			}
1474 			read_count = libbfio_handle_read_buffer(
1475 				      file_io_handle,
1476 				      trailing_data,
1477 				      trailing_data_size,
1478 				      error );
1479 
1480 			if( read_count != (ssize_t) trailing_data_size )
1481 			{
1482 				libcerror_error_set(
1483 				 error,
1484 				 LIBCERROR_ERROR_DOMAIN_IO,
1485 				 LIBCERROR_IO_ERROR_READ_FAILED,
1486 				 "%s: unable to read trailing data.",
1487 				 function );
1488 
1489 				memory_free(
1490 				 trailing_data );
1491 
1492 				goto on_error;
1493 			}
1494 			file_offset += read_count;
1495 
1496 			libcnotify_printf(
1497 			 "%s: trailing data:\n",
1498 			 function );
1499 			libcnotify_print_data(
1500 			 trailing_data,
1501 			 trailing_data_size,
1502 			 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1503 
1504 			memory_free(
1505 			 trailing_data );
1506 
1507 			trailing_data = NULL;
1508 		}
1509 	}
1510 #endif
1511 	return( 1 );
1512 
1513 on_error:
1514 #if defined( HAVE_DEBUG_OUTPUT )
1515 	if( trailing_data != NULL )
1516 	{
1517 		memory_free(
1518 		 trailing_data );
1519 	}
1520 #endif
1521 	if( chunk != NULL )
1522 	{
1523 		libevtx_chunk_free(
1524 		 &chunk,
1525 		 NULL );
1526 	}
1527 	if( internal_file->records_cache != NULL )
1528 	{
1529 		libfcache_cache_free(
1530 		 &( internal_file->records_cache ),
1531 		 NULL );
1532 	}
1533 	if( internal_file->recovered_records_list != NULL )
1534 	{
1535 		libfdata_list_free(
1536 		 &( internal_file->recovered_records_list ),
1537 		 NULL );
1538 	}
1539 	if( internal_file->records_list != NULL )
1540 	{
1541 		libfdata_list_free(
1542 		 &( internal_file->records_list ),
1543 		 NULL );
1544 	}
1545 	if( chunks_table != NULL )
1546 	{
1547 		libevtx_chunks_table_free(
1548 		 &chunks_table,
1549 		 NULL );
1550 	}
1551 	if( internal_file->chunks_cache != NULL )
1552 	{
1553 		libfcache_cache_free(
1554 		 &( internal_file->chunks_cache ),
1555 		 NULL );
1556 	}
1557 	if( internal_file->chunks_vector != NULL )
1558 	{
1559 		libfdata_vector_free(
1560 		 &( internal_file->chunks_vector ),
1561 		 NULL );
1562 	}
1563 	return( -1 );
1564 }
1565 
1566 /* Determine if the file corrupted
1567  * Returns 1 if corrupted, 0 if not or -1 on error
1568  */
libevtx_file_is_corrupted(libevtx_file_t * file,libcerror_error_t ** error)1569 int libevtx_file_is_corrupted(
1570      libevtx_file_t *file,
1571      libcerror_error_t **error )
1572 {
1573 	libevtx_internal_file_t *internal_file = NULL;
1574 	static char *function                  = "libevtx_file_is_corrupted";
1575 
1576 	if( file == NULL )
1577 	{
1578 		libcerror_error_set(
1579 		 error,
1580 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1581 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1582 		 "%s: invalid file.",
1583 		 function );
1584 
1585 		return( -1 );
1586 	}
1587 	internal_file = (libevtx_internal_file_t *) file;
1588 
1589 	if( internal_file->io_handle == NULL )
1590 	{
1591 		libcerror_error_set(
1592 		 error,
1593 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1594 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1595 		 "%s: invalid file - missing IO handle.",
1596 		 function );
1597 
1598 		return( -1 );
1599 	}
1600 	if( ( internal_file->io_handle->flags & LIBEVTX_IO_HANDLE_FLAG_IS_CORRUPTED ) != 0 )
1601 	{
1602 		return( 1 );
1603 	}
1604 	return( 0 );
1605 }
1606 
1607 /* Retrieves the file ASCII codepage
1608  * Returns 1 if successful or -1 on error
1609  */
libevtx_file_get_ascii_codepage(libevtx_file_t * file,int * ascii_codepage,libcerror_error_t ** error)1610 int libevtx_file_get_ascii_codepage(
1611      libevtx_file_t *file,
1612      int *ascii_codepage,
1613      libcerror_error_t **error )
1614 {
1615 	libevtx_internal_file_t *internal_file = NULL;
1616 	static char *function                  = "libevtx_file_get_ascii_codepage";
1617 
1618 	if( file == NULL )
1619 	{
1620 		libcerror_error_set(
1621 		 error,
1622 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1623 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1624 		 "%s: invalid file.",
1625 		 function );
1626 
1627 		return( -1 );
1628 	}
1629 	internal_file = (libevtx_internal_file_t *) file;
1630 
1631 	if( internal_file->io_handle == NULL )
1632 	{
1633 		libcerror_error_set(
1634 		 error,
1635 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1636 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1637 		 "%s: invalid file - missing IO handle.",
1638 		 function );
1639 
1640 		return( -1 );
1641 	}
1642 	if( ascii_codepage == NULL )
1643 	{
1644 		libcerror_error_set(
1645 		 error,
1646 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1647 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1648 		 "%s: invalid ASCII codepage.",
1649 		 function );
1650 
1651 		return( -1 );
1652 	}
1653 	*ascii_codepage = internal_file->io_handle->ascii_codepage;
1654 
1655 	return( 1 );
1656 }
1657 
1658 /* Sets the file ASCII codepage
1659  * Returns 1 if successful or -1 on error
1660  */
libevtx_file_set_ascii_codepage(libevtx_file_t * file,int ascii_codepage,libcerror_error_t ** error)1661 int libevtx_file_set_ascii_codepage(
1662      libevtx_file_t *file,
1663      int ascii_codepage,
1664      libcerror_error_t **error )
1665 {
1666 	libevtx_internal_file_t *internal_file = NULL;
1667 	static char *function                  = "libevtx_file_set_ascii_codepage";
1668 
1669 	if( file == NULL )
1670 	{
1671 		libcerror_error_set(
1672 		 error,
1673 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1674 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1675 		 "%s: invalid file.",
1676 		 function );
1677 
1678 		return( -1 );
1679 	}
1680 	internal_file = (libevtx_internal_file_t *) file;
1681 
1682 	if( internal_file->io_handle == NULL )
1683 	{
1684 		libcerror_error_set(
1685 		 error,
1686 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1687 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1688 		 "%s: invalid file - missing IO handle.",
1689 		 function );
1690 
1691 		return( -1 );
1692 	}
1693 	if( ( ascii_codepage != LIBEVTX_CODEPAGE_ASCII )
1694 	 && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_874 )
1695 	 && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_932 )
1696 	 && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_936 )
1697 	 && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_949 )
1698 	 && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_950 )
1699 	 && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1250 )
1700 	 && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1251 )
1701 	 && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1252 )
1702 	 && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1253 )
1703 	 && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1254 )
1704 	 && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1255 )
1705 	 && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1256 )
1706 	 && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1257 )
1707 	 && ( ascii_codepage != LIBEVTX_CODEPAGE_WINDOWS_1258 ) )
1708 	{
1709 		libcerror_error_set(
1710 		 error,
1711 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1712 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1713 		 "%s: unsupported ASCII codepage.",
1714 		 function );
1715 
1716 		return( -1 );
1717 	}
1718 	internal_file->io_handle->ascii_codepage = ascii_codepage;
1719 
1720 	return( 1 );
1721 }
1722 
1723 /* Retrieves the format version
1724  * Returns 1 if successful or -1 on error
1725  */
libevtx_file_get_format_version(libevtx_file_t * file,uint16_t * major_version,uint16_t * minor_version,libcerror_error_t ** error)1726 int libevtx_file_get_format_version(
1727      libevtx_file_t *file,
1728      uint16_t *major_version,
1729      uint16_t *minor_version,
1730      libcerror_error_t **error )
1731 {
1732 	libevtx_internal_file_t *internal_file = NULL;
1733 	static char *function                  = "libevtx_file_get_format_version";
1734 
1735 	if( file == NULL )
1736 	{
1737 		libcerror_error_set(
1738 		 error,
1739 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1740 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1741 		 "%s: invalid file.",
1742 		 function );
1743 
1744 		return( -1 );
1745 	}
1746 	internal_file = (libevtx_internal_file_t *) file;
1747 
1748 	if( internal_file->io_handle == NULL )
1749 	{
1750 		libcerror_error_set(
1751 		 error,
1752 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1753 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1754 		 "%s: invalid file - missing IO handle.",
1755 		 function );
1756 
1757 		return( -1 );
1758 	}
1759 	if( major_version == NULL )
1760 	{
1761 		libcerror_error_set(
1762 		 error,
1763 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1764 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1765 		 "%s: invalid major version.",
1766 		 function );
1767 
1768 		return( -1 );
1769 	}
1770 	if( minor_version == NULL )
1771 	{
1772 		libcerror_error_set(
1773 		 error,
1774 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1775 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1776 		 "%s: invalid minor version.",
1777 		 function );
1778 
1779 		return( -1 );
1780 	}
1781 	*major_version = internal_file->io_handle->major_version;
1782 	*minor_version = internal_file->io_handle->minor_version;
1783 
1784 	return( 1 );
1785 }
1786 
1787 /* Retrieves the file version
1788  * Returns 1 if successful or -1 on error
1789  */
libevtx_file_get_version(libevtx_file_t * file,uint16_t * major_version,uint16_t * minor_version,libcerror_error_t ** error)1790 int libevtx_file_get_version(
1791      libevtx_file_t *file,
1792      uint16_t *major_version,
1793      uint16_t *minor_version,
1794      libcerror_error_t **error )
1795 {
1796 	libevtx_internal_file_t *internal_file = NULL;
1797 	static char *function                  = "libevtx_file_get_version";
1798 
1799 	if( file == NULL )
1800 	{
1801 		libcerror_error_set(
1802 		 error,
1803 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1804 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1805 		 "%s: invalid file.",
1806 		 function );
1807 
1808 		return( -1 );
1809 	}
1810 	internal_file = (libevtx_internal_file_t *) file;
1811 
1812 	if( internal_file->io_handle == NULL )
1813 	{
1814 		libcerror_error_set(
1815 		 error,
1816 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1817 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1818 		 "%s: invalid file - missing IO handle.",
1819 		 function );
1820 
1821 		return( -1 );
1822 	}
1823 	if( major_version == NULL )
1824 	{
1825 		libcerror_error_set(
1826 		 error,
1827 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1828 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1829 		 "%s: invalid major version.",
1830 		 function );
1831 
1832 		return( -1 );
1833 	}
1834 	if( minor_version == NULL )
1835 	{
1836 		libcerror_error_set(
1837 		 error,
1838 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1839 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1840 		 "%s: invalid minor version.",
1841 		 function );
1842 
1843 		return( -1 );
1844 	}
1845 	*major_version = internal_file->io_handle->major_version;
1846 	*minor_version = internal_file->io_handle->minor_version;
1847 
1848 	return( 1 );
1849 }
1850 
1851 /* Retrieves the flags
1852  * Returns 1 if successful or -1 on error
1853  */
libevtx_file_get_flags(libevtx_file_t * file,uint32_t * flags,libcerror_error_t ** error)1854 int libevtx_file_get_flags(
1855      libevtx_file_t *file,
1856      uint32_t *flags,
1857      libcerror_error_t **error )
1858 {
1859 	libevtx_internal_file_t *internal_file = NULL;
1860 	static char *function                  = "libevtx_file_get_flags";
1861 
1862 	if( file == NULL )
1863 	{
1864 		libcerror_error_set(
1865 		 error,
1866 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1867 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1868 		 "%s: invalid file.",
1869 		 function );
1870 
1871 		return( -1 );
1872 	}
1873 	internal_file = (libevtx_internal_file_t *) file;
1874 
1875 	if( internal_file->io_handle == NULL )
1876 	{
1877 		libcerror_error_set(
1878 		 error,
1879 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1880 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1881 		 "%s: invalid file - missing IO handle.",
1882 		 function );
1883 
1884 		return( -1 );
1885 	}
1886 	if( flags == NULL )
1887 	{
1888 		libcerror_error_set(
1889 		 error,
1890 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1891 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1892 		 "%s: invalid flags.",
1893 		 function );
1894 
1895 		return( -1 );
1896 	}
1897 	*flags = internal_file->io_handle->file_flags;
1898 
1899 	return( 1 );
1900 }
1901 
1902 /* Retrieves the number of records
1903  * Returns 1 if successful or -1 on error
1904  */
libevtx_file_get_number_of_records(libevtx_file_t * file,int * number_of_records,libcerror_error_t ** error)1905 int libevtx_file_get_number_of_records(
1906      libevtx_file_t *file,
1907      int *number_of_records,
1908      libcerror_error_t **error )
1909 {
1910 	libevtx_internal_file_t *internal_file = NULL;
1911 	static char *function                  = "libevtx_file_get_number_of_records";
1912 
1913 	if( file == NULL )
1914 	{
1915 		libcerror_error_set(
1916 		 error,
1917 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1918 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1919 		 "%s: invalid file.",
1920 		 function );
1921 
1922 		return( -1 );
1923 	}
1924 	internal_file = (libevtx_internal_file_t *) file;
1925 
1926 	if( libfdata_list_get_number_of_elements(
1927 	     internal_file->records_list,
1928 	     number_of_records,
1929 	     error ) != 1 )
1930 	{
1931 		libcerror_error_set(
1932 		 error,
1933 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1934 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1935 		 "%s: unable to retrieve number of records.",
1936 		 function );
1937 
1938 		return( -1 );
1939 	}
1940 	return( 1 );
1941 }
1942 
1943 /* Retrieves a specific record
1944  * Returns 1 if successful or -1 on error
1945  */
libevtx_file_get_record(libevtx_file_t * file,int record_index,libevtx_record_t ** record,libcerror_error_t ** error)1946 int libevtx_file_get_record(
1947      libevtx_file_t *file,
1948      int record_index,
1949      libevtx_record_t **record,
1950      libcerror_error_t **error )
1951 {
1952 	libevtx_internal_file_t *internal_file = NULL;
1953 	libevtx_record_values_t *record_values = NULL;
1954 	static char *function                  = "libevtx_file_get_record";
1955 
1956 	if( file == NULL )
1957 	{
1958 		libcerror_error_set(
1959 		 error,
1960 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1961 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1962 		 "%s: invalid file.",
1963 		 function );
1964 
1965 		return( -1 );
1966 	}
1967 	internal_file = (libevtx_internal_file_t *) file;
1968 
1969 	if( record == NULL )
1970 	{
1971 		libcerror_error_set(
1972 		 error,
1973 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1974 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1975 		 "%s: invalid record.",
1976 		 function );
1977 
1978 		return( -1 );
1979 	}
1980 	if( libfdata_list_get_element_value_by_index(
1981 	     internal_file->records_list,
1982 	     (intptr_t *) internal_file->file_io_handle,
1983 	     (libfdata_cache_t *) internal_file->records_cache,
1984 	     record_index,
1985 	     (intptr_t **) &record_values,
1986 	     0,
1987 	     error ) != 1 )
1988 	{
1989 		libcerror_error_set(
1990 		 error,
1991 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1992 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1993 		 "%s: unable to retrieve record values: %d.",
1994 		 function,
1995 		 record_index );
1996 
1997 		return( -1 );
1998 	}
1999 	if( libevtx_record_initialize(
2000 	     record,
2001 	     internal_file->io_handle,
2002 	     internal_file->file_io_handle,
2003 	     record_values,
2004 	     LIBEVTX_RECORD_FLAGS_DEFAULT,
2005 	     error ) != 1 )
2006 	{
2007 		libcerror_error_set(
2008 		 error,
2009 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2010 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2011 		 "%s: unable to create record.",
2012 		 function );
2013 
2014 		return( -1 );
2015 	}
2016 	return( 1 );
2017 }
2018 
2019 /* Retrieves a specific record
2020  * Returns 1 if successful or -1 on error
2021  */
libevtx_file_get_record_by_index(libevtx_file_t * file,int record_index,libevtx_record_t ** record,libcerror_error_t ** error)2022 int libevtx_file_get_record_by_index(
2023      libevtx_file_t *file,
2024      int record_index,
2025      libevtx_record_t **record,
2026      libcerror_error_t **error )
2027 {
2028 	libevtx_internal_file_t *internal_file = NULL;
2029 	libevtx_record_values_t *record_values = NULL;
2030 	static char *function                  = "libevtx_file_get_record_by_index";
2031 
2032 	if( file == NULL )
2033 	{
2034 		libcerror_error_set(
2035 		 error,
2036 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2037 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2038 		 "%s: invalid file.",
2039 		 function );
2040 
2041 		return( -1 );
2042 	}
2043 	internal_file = (libevtx_internal_file_t *) file;
2044 
2045 	if( record == NULL )
2046 	{
2047 		libcerror_error_set(
2048 		 error,
2049 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2050 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2051 		 "%s: invalid record.",
2052 		 function );
2053 
2054 		return( -1 );
2055 	}
2056 	if( libfdata_list_get_element_value_by_index(
2057 	     internal_file->records_list,
2058 	     (intptr_t *) internal_file->file_io_handle,
2059 	     (libfdata_cache_t *) internal_file->records_cache,
2060 	     record_index,
2061 	     (intptr_t **) &record_values,
2062 	     0,
2063 	     error ) != 1 )
2064 	{
2065 		libcerror_error_set(
2066 		 error,
2067 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2068 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2069 		 "%s: unable to retrieve record values: %d.",
2070 		 function,
2071 		 record_index );
2072 
2073 		return( -1 );
2074 	}
2075 	if( libevtx_record_initialize(
2076 	     record,
2077 	     internal_file->io_handle,
2078 	     internal_file->file_io_handle,
2079 	     record_values,
2080 	     LIBEVTX_RECORD_FLAGS_DEFAULT,
2081 	     error ) != 1 )
2082 	{
2083 		libcerror_error_set(
2084 		 error,
2085 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2086 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2087 		 "%s: unable to create record.",
2088 		 function );
2089 
2090 		return( -1 );
2091 	}
2092 	return( 1 );
2093 }
2094 
2095 /* Retrieves the number of recovered records
2096  * Returns 1 if successful or -1 on error
2097  */
libevtx_file_get_number_of_recovered_records(libevtx_file_t * file,int * number_of_records,libcerror_error_t ** error)2098 int libevtx_file_get_number_of_recovered_records(
2099      libevtx_file_t *file,
2100      int *number_of_records,
2101      libcerror_error_t **error )
2102 {
2103 	libevtx_internal_file_t *internal_file = NULL;
2104 	static char *function                  = "libevtx_file_get_number_of_recovered_records";
2105 
2106 	if( file == NULL )
2107 	{
2108 		libcerror_error_set(
2109 		 error,
2110 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2111 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2112 		 "%s: invalid file.",
2113 		 function );
2114 
2115 		return( -1 );
2116 	}
2117 	internal_file = (libevtx_internal_file_t *) file;
2118 
2119 	if( libfdata_list_get_number_of_elements(
2120 	     internal_file->recovered_records_list,
2121 	     number_of_records,
2122 	     error ) != 1 )
2123 	{
2124 		libcerror_error_set(
2125 		 error,
2126 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2127 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2128 		 "%s: unable to retrieve number of records.",
2129 		 function );
2130 
2131 		return( -1 );
2132 	}
2133 	return( 1 );
2134 }
2135 
2136 /* Retrieves a specific recovered record
2137  * Returns 1 if successful or -1 on error
2138  */
libevtx_file_get_recovered_record(libevtx_file_t * file,int record_index,libevtx_record_t ** record,libcerror_error_t ** error)2139 int libevtx_file_get_recovered_record(
2140      libevtx_file_t *file,
2141      int record_index,
2142      libevtx_record_t **record,
2143      libcerror_error_t **error )
2144 {
2145 	libevtx_internal_file_t *internal_file = NULL;
2146 	libevtx_record_values_t *record_values = NULL;
2147 	static char *function                  = "libevtx_file_get_recovered_record";
2148 
2149 	if( file == NULL )
2150 	{
2151 		libcerror_error_set(
2152 		 error,
2153 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2154 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2155 		 "%s: invalid file.",
2156 		 function );
2157 
2158 		return( -1 );
2159 	}
2160 	internal_file = (libevtx_internal_file_t *) file;
2161 
2162 	if( record == NULL )
2163 	{
2164 		libcerror_error_set(
2165 		 error,
2166 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2167 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2168 		 "%s: invalid record.",
2169 		 function );
2170 
2171 		return( -1 );
2172 	}
2173 	if( libfdata_list_get_element_value_by_index(
2174 	     internal_file->recovered_records_list,
2175 	     (intptr_t *) internal_file->file_io_handle,
2176 	     (libfdata_cache_t *) internal_file->records_cache,
2177 	     record_index,
2178 	     (intptr_t **) &record_values,
2179 	     0,
2180 	     error ) != 1 )
2181 	{
2182 		libcerror_error_set(
2183 		 error,
2184 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2185 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2186 		 "%s: unable to retrieve record values: %d.",
2187 		 function,
2188 		 record_index );
2189 
2190 		return( -1 );
2191 	}
2192 	if( libevtx_record_initialize(
2193 	     record,
2194 	     internal_file->io_handle,
2195 	     internal_file->file_io_handle,
2196 	     record_values,
2197 	     LIBEVTX_RECORD_FLAGS_DEFAULT,
2198 	     error ) != 1 )
2199 	{
2200 		libcerror_error_set(
2201 		 error,
2202 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2203 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2204 		 "%s: unable to create record.",
2205 		 function );
2206 
2207 		return( -1 );
2208 	}
2209 	return( 1 );
2210 }
2211 
2212 /* Retrieves a specific recovered record
2213  * Returns 1 if successful or -1 on error
2214  */
libevtx_file_get_recovered_record_by_index(libevtx_file_t * file,int record_index,libevtx_record_t ** record,libcerror_error_t ** error)2215 int libevtx_file_get_recovered_record_by_index(
2216      libevtx_file_t *file,
2217      int record_index,
2218      libevtx_record_t **record,
2219      libcerror_error_t **error )
2220 {
2221 	libevtx_internal_file_t *internal_file = NULL;
2222 	libevtx_record_values_t *record_values = NULL;
2223 	static char *function                  = "libevtx_file_get_recovered_record_by_index";
2224 
2225 	if( file == NULL )
2226 	{
2227 		libcerror_error_set(
2228 		 error,
2229 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2230 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2231 		 "%s: invalid file.",
2232 		 function );
2233 
2234 		return( -1 );
2235 	}
2236 	internal_file = (libevtx_internal_file_t *) file;
2237 
2238 	if( record == NULL )
2239 	{
2240 		libcerror_error_set(
2241 		 error,
2242 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2243 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2244 		 "%s: invalid record.",
2245 		 function );
2246 
2247 		return( -1 );
2248 	}
2249 	if( libfdata_list_get_element_value_by_index(
2250 	     internal_file->recovered_records_list,
2251 	     (intptr_t *) internal_file->file_io_handle,
2252 	     (libfdata_cache_t *) internal_file->records_cache,
2253 	     record_index,
2254 	     (intptr_t **) &record_values,
2255 	     0,
2256 	     error ) != 1 )
2257 	{
2258 		libcerror_error_set(
2259 		 error,
2260 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2261 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2262 		 "%s: unable to retrieve record values: %d.",
2263 		 function,
2264 		 record_index );
2265 
2266 		return( -1 );
2267 	}
2268 	if( libevtx_record_initialize(
2269 	     record,
2270 	     internal_file->io_handle,
2271 	     internal_file->file_io_handle,
2272 	     record_values,
2273 	     LIBEVTX_RECORD_FLAGS_DEFAULT,
2274 	     error ) != 1 )
2275 	{
2276 		libcerror_error_set(
2277 		 error,
2278 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2279 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2280 		 "%s: unable to create record.",
2281 		 function );
2282 
2283 		return( -1 );
2284 	}
2285 	return( 1 );
2286 }
2287 
2288