1 /*
2  * Record entry functions
3  *
4  * Copyright (C) 2008-2018, Joachim Metz <joachim.metz@gmail.com>
5  *
6  * Refer to AUTHORS for acknowledgements.
7  *
8  * This software 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 software 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 software.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <common.h>
23 #include <byte_stream.h>
24 #include <memory.h>
25 #include <types.h>
26 
27 #include "libpff_definitions.h"
28 #include "libpff_descriptor_data_stream.h"
29 #include "libpff_libcerror.h"
30 #include "libpff_libuna.h"
31 #include "libpff_mapi.h"
32 #include "libpff_mapi_value.h"
33 #include "libpff_multi_value.h"
34 #include "libpff_record_entry.h"
35 #include "libpff_record_entry_identifier.h"
36 
37 /* Creates a record entry
38  * Make sure the value record_entry is referencing, is set to NULL
39  * Returns 1 if successful or -1 on error
40  */
libpff_record_entry_initialize(libpff_record_entry_t ** record_entry,int ascii_codepage,libcerror_error_t ** error)41 int libpff_record_entry_initialize(
42      libpff_record_entry_t **record_entry,
43      int ascii_codepage,
44      libcerror_error_t **error )
45 {
46 	libpff_internal_record_entry_t *internal_record_entry = NULL;
47 	static char *function                                 = "libpff_record_entry_initialize";
48 
49 	if( record_entry == NULL )
50 	{
51 		libcerror_error_set(
52 		 error,
53 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
54 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
55 		 "%s: invalid record entry.",
56 		 function );
57 
58 		return( -1 );
59 	}
60 	if( *record_entry != NULL )
61 	{
62 		libcerror_error_set(
63 		 error,
64 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
65 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
66 		 "%s: invalid record entry value already set.",
67 		 function );
68 
69 		return( -1 );
70 	}
71 	internal_record_entry = memory_allocate_structure(
72 	                         libpff_internal_record_entry_t );
73 
74 	if( internal_record_entry == NULL )
75 	{
76 		libcerror_error_set(
77 		 error,
78 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
79 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
80 		 "%s: unable to create record entry.",
81 		 function );
82 
83 		goto on_error;
84 	}
85 	if( memory_set(
86 	     internal_record_entry,
87 	     0,
88 	     sizeof( libpff_internal_record_entry_t ) ) == NULL )
89 	{
90 		libcerror_error_set(
91 		 error,
92 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
93 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
94 		 "%s: unable to clear record entry.",
95 		 function );
96 
97 		goto on_error;
98 	}
99 	internal_record_entry->ascii_codepage = ascii_codepage;
100 
101 	*record_entry = (libpff_record_entry_t *) internal_record_entry;
102 
103 	return( 1 );
104 
105 on_error:
106 	if( internal_record_entry != NULL )
107 	{
108 		memory_free(
109 		 internal_record_entry );
110 	}
111 	return( -1 );
112 }
113 
114 /* Frees a record entry
115  * Returns 1 if successful or -1 on error
116  */
libpff_record_entry_free(libpff_record_entry_t ** record_entry,libcerror_error_t ** error)117 int libpff_record_entry_free(
118      libpff_record_entry_t **record_entry,
119      libcerror_error_t **error )
120 {
121 	static char *function = "libpff_record_entry_free";
122 
123 	if( record_entry == NULL )
124 	{
125 		libcerror_error_set(
126 		 error,
127 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
128 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
129 		 "%s: invalid record entry.",
130 		 function );
131 
132 		return( -1 );
133 	}
134 	if( *record_entry != NULL )
135 	{
136 		*record_entry = NULL;
137 	}
138 	return( 1 );
139 }
140 
141 /* Frees a record entry
142  * Returns 1 if successful or -1 on error
143  */
libpff_internal_record_entry_free(libpff_internal_record_entry_t ** internal_record_entry,libcerror_error_t ** error)144 int libpff_internal_record_entry_free(
145      libpff_internal_record_entry_t **internal_record_entry,
146      libcerror_error_t **error )
147 {
148 	static char *function = "libpff_internal_record_entry_free";
149 
150 	if( internal_record_entry == NULL )
151 	{
152 		libcerror_error_set(
153 		 error,
154 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
155 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
156 		 "%s: invalid record entry.",
157 		 function );
158 
159 		return( -1 );
160 	}
161 	if( *internal_record_entry != NULL )
162 	{
163 		if( ( *internal_record_entry )->value_data != NULL )
164 		{
165 			memory_free(
166 			 ( *internal_record_entry )->value_data );
167 		}
168 		memory_free(
169 		 *internal_record_entry );
170 
171 		*internal_record_entry = NULL;
172 	}
173 	return( 1 );
174 }
175 
176 /* Clones the record entry
177  * Returns 1 if successful or -1 on error
178  */
libpff_record_entry_clone(libpff_record_entry_t ** destination_record_entry,libpff_record_entry_t * source_record_entry,libcerror_error_t ** error)179 int libpff_record_entry_clone(
180      libpff_record_entry_t **destination_record_entry,
181      libpff_record_entry_t *source_record_entry,
182      libcerror_error_t **error )
183 {
184 	libpff_internal_record_entry_t *internal_destination_record_entry = NULL;
185 	libpff_internal_record_entry_t *internal_source_record_entry      = NULL;
186 	static char *function                                             = "libpff_record_entry_clone";
187 
188 	if( destination_record_entry == NULL )
189 	{
190 		libcerror_error_set(
191 		 error,
192 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
193 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
194 		 "%s: invalid record entry.",
195 		 function );
196 
197 		return( -1 );
198 	}
199 	if( *destination_record_entry != NULL )
200 	{
201 		libcerror_error_set(
202 		 error,
203 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
204 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
205 		 "%s: invalid destination record entry value already set.",
206 		 function );
207 
208 		return( -1 );
209 	}
210 	if( source_record_entry == NULL )
211 	{
212 		*destination_record_entry = NULL;
213 
214 		return( 1 );
215 	}
216 	internal_source_record_entry = (libpff_internal_record_entry_t *) source_record_entry;
217 
218 	if( libpff_record_entry_initialize(
219 	     (libpff_record_entry_t **) &internal_destination_record_entry,
220 	     internal_source_record_entry->ascii_codepage,
221 	     error ) != 1 )
222 	{
223 		libcerror_error_set(
224 		 error,
225 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
226 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
227 		 "%s: unable to create destination record entry.",
228 		 function );
229 
230 		goto on_error;
231 	}
232 	if( internal_destination_record_entry == NULL )
233 	{
234 		libcerror_error_set(
235 		 error,
236 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
237 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
238 		 "%s: missing destination record entry.",
239 		 function );
240 
241 		goto on_error;
242 	}
243 	if( memory_copy(
244 	     &( internal_destination_record_entry->identifier ),
245 	     &( internal_source_record_entry->identifier ),
246 	     sizeof( libpff_record_entry_identifier_t ) ) == NULL )
247 	{
248 		libcerror_error_set(
249 		 error,
250 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
251 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
252 		 "%s: unable to copy identifier.",
253 		 function );
254 
255 		goto on_error;
256 	}
257 	internal_destination_record_entry->value_data      = NULL;
258 	internal_destination_record_entry->value_data_size = 0;
259 
260 	if( internal_source_record_entry->value_data != NULL )
261 	{
262 		internal_destination_record_entry->value_data = (uint8_t *) memory_allocate(
263 		                                                             internal_source_record_entry->value_data_size );
264 
265 		if( internal_destination_record_entry->value_data == NULL )
266 		{
267 			libcerror_error_set(
268 			 error,
269 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
270 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
271 			 "%s: unable to create value data.",
272 			 function );
273 
274 			goto on_error;
275 		}
276 		if( memory_copy(
277 		     internal_destination_record_entry->value_data,
278 		     internal_source_record_entry->value_data,
279 		     internal_source_record_entry->value_data_size ) == NULL )
280 		{
281 			libcerror_error_set(
282 			 error,
283 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
284 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
285 			 "%s: unable to copy value data.",
286 			 function );
287 
288 			goto on_error;
289 		}
290 		internal_destination_record_entry->value_data_size = internal_source_record_entry->value_data_size;
291 	}
292 	internal_destination_record_entry->name_to_id_map_entry = internal_source_record_entry->name_to_id_map_entry;
293 	internal_destination_record_entry->flags                = internal_source_record_entry->flags;
294 
295 	*destination_record_entry = (libpff_record_entry_t *) internal_destination_record_entry;
296 
297 	return( 1 );
298 
299 on_error:
300 	if( internal_destination_record_entry != NULL )
301 	{
302 		libpff_internal_record_entry_free(
303 		 &internal_destination_record_entry,
304 		 NULL );
305 	}
306 	return( -1 );
307 }
308 
309 /* Retrieves the entry type
310  * Returns 1 if successful, 0 if not available or -1 on error
311  */
libpff_record_entry_get_entry_type(libpff_record_entry_t * record_entry,uint32_t * entry_type,libcerror_error_t ** error)312 int libpff_record_entry_get_entry_type(
313      libpff_record_entry_t *record_entry,
314      uint32_t *entry_type,
315      libcerror_error_t **error )
316 {
317 	libpff_internal_record_entry_t *internal_record_entry = NULL;
318 	static char *function                                 = "libpff_record_entry_get_entry_type";
319 
320 	if( record_entry == NULL )
321 	{
322 		libcerror_error_set(
323 		 error,
324 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
325 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
326 		 "%s: invalid record entry.",
327 		 function );
328 
329 		return( -1 );
330 	}
331 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
332 
333 	if( entry_type == NULL )
334 	{
335 		libcerror_error_set(
336 		 error,
337 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
338 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
339 		 "%s: invalid entry type.",
340 		 function );
341 
342 		return( -1 );
343 	}
344 	if( internal_record_entry->identifier.format != LIBPFF_RECORD_ENTRY_IDENTIFIER_FORMAT_MAPI_PROPERTY )
345 	{
346 		return( 0 );
347 	}
348 	*entry_type = internal_record_entry->identifier.entry_type;
349 
350 	return( 1 );
351 }
352 
353 /* Retrieves the value type
354  * Returns 1 if successful, 0 if not available or -1 on error
355  */
libpff_record_entry_get_value_type(libpff_record_entry_t * record_entry,uint32_t * value_type,libcerror_error_t ** error)356 int libpff_record_entry_get_value_type(
357      libpff_record_entry_t *record_entry,
358      uint32_t *value_type,
359      libcerror_error_t **error )
360 {
361 	libpff_internal_record_entry_t *internal_record_entry = NULL;
362 	static char *function                                 = "libpff_record_entry_get_value_type";
363 
364 	if( record_entry == NULL )
365 	{
366 		libcerror_error_set(
367 		 error,
368 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
369 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
370 		 "%s: invalid record entry.",
371 		 function );
372 
373 		return( -1 );
374 	}
375 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
376 
377 	if( value_type == NULL )
378 	{
379 		libcerror_error_set(
380 		 error,
381 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
382 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
383 		 "%s: invalid value type.",
384 		 function );
385 
386 		return( -1 );
387 	}
388 	if( internal_record_entry->identifier.format != LIBPFF_RECORD_ENTRY_IDENTIFIER_FORMAT_MAPI_PROPERTY )
389 	{
390 		return( 0 );
391 	}
392 	*value_type = internal_record_entry->identifier.value_type;
393 
394 	return( 1 );
395 }
396 
397 /* Retrieves the name to ID map entry
398  * Returns 1 if successful, 0 if not available or -1 on error
399  */
libpff_record_entry_get_name_to_id_map_entry(libpff_record_entry_t * record_entry,libpff_name_to_id_map_entry_t ** name_to_id_map_entry,libcerror_error_t ** error)400 int libpff_record_entry_get_name_to_id_map_entry(
401      libpff_record_entry_t *record_entry,
402      libpff_name_to_id_map_entry_t **name_to_id_map_entry,
403      libcerror_error_t **error )
404 {
405 	libpff_internal_record_entry_t *internal_record_entry = NULL;
406 	static char *function                                 = "libpff_record_entry_get_name_to_id_map_entry";
407 
408 	if( record_entry == NULL )
409 	{
410 		libcerror_error_set(
411 		 error,
412 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
413 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
414 		 "%s: invalid record entry.",
415 		 function );
416 
417 		return( -1 );
418 	}
419 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
420 
421 	if( name_to_id_map_entry == NULL )
422 	{
423 		libcerror_error_set(
424 		 error,
425 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
426 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
427 		 "%s: invalid name to ID map entry.",
428 		 function );
429 
430 		return( -1 );
431 	}
432 	if( ( internal_record_entry->identifier.format != LIBPFF_RECORD_ENTRY_IDENTIFIER_FORMAT_MAPI_PROPERTY )
433 	 || ( internal_record_entry->name_to_id_map_entry == NULL ) )
434 	{
435 		return( 0 );
436 	}
437 	*name_to_id_map_entry = (libpff_name_to_id_map_entry_t *) internal_record_entry->name_to_id_map_entry;
438 
439 	return( 1 );
440 }
441 
442 /* Retrieves the data size
443  * Returns 1 if successful or -1 on error
444  */
libpff_record_entry_get_data_size(libpff_record_entry_t * record_entry,size_t * data_size,libcerror_error_t ** error)445 int libpff_record_entry_get_data_size(
446      libpff_record_entry_t *record_entry,
447      size_t *data_size,
448      libcerror_error_t **error )
449 {
450 	libpff_internal_record_entry_t *internal_record_entry = NULL;
451 	static char *function                                 = "libpff_record_entry_get_data_size";
452 
453 	if( record_entry == NULL )
454 	{
455 		libcerror_error_set(
456 		 error,
457 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
458 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
459 		 "%s: invalid record entry.",
460 		 function );
461 
462 		return( -1 );
463 	}
464 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
465 
466 	if( data_size == NULL )
467 	{
468 		libcerror_error_set(
469 		 error,
470 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
471 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
472 		 "%s: invalid data size.",
473 		 function );
474 
475 		return( -1 );
476 	}
477 	*data_size = internal_record_entry->value_data_size;
478 
479 	return( 1 );
480 }
481 
482 /* Retrieves the value data
483  * Returns 1 if successful or -1 on error
484  */
libpff_record_entry_get_value_data(libpff_record_entry_t * record_entry,uint8_t ** value_data,size_t * value_data_size,libcerror_error_t ** error)485 int libpff_record_entry_get_value_data(
486      libpff_record_entry_t *record_entry,
487      uint8_t **value_data,
488      size_t *value_data_size,
489      libcerror_error_t **error )
490 {
491 	libpff_internal_record_entry_t *internal_record_entry = NULL;
492 	static char *function                                 = "libpff_record_entry_get_value_data";
493 
494 	if( record_entry == NULL )
495 	{
496 		libcerror_error_set(
497 		 error,
498 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
499 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
500 		 "%s: invalid record entry.",
501 		 function );
502 
503 		return( -1 );
504 	}
505 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
506 
507 	if( value_data == NULL )
508 	{
509 		libcerror_error_set(
510 		 error,
511 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
512 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
513 		 "%s: invalid value data.",
514 		 function );
515 
516 		return( -1 );
517 	}
518 	if( value_data_size == NULL )
519 	{
520 		libcerror_error_set(
521 		 error,
522 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
523 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
524 		 "%s: invalid value data size.",
525 		 function );
526 
527 		return( -1 );
528 	}
529 	*value_data      = internal_record_entry->value_data;
530 	*value_data_size = internal_record_entry->value_data_size;
531 
532 	return( 1 );
533 }
534 
535 /* Sets the value data in the record entry
536  * The function makes a local copy
537  * Returns 1 if successful or -1 on error
538  */
libpff_record_entry_set_value_data(libpff_record_entry_t * record_entry,const uint8_t * value_data,size_t value_data_size,libcerror_error_t ** error)539 int libpff_record_entry_set_value_data(
540      libpff_record_entry_t *record_entry,
541      const uint8_t *value_data,
542      size_t value_data_size,
543      libcerror_error_t **error )
544 {
545 	libpff_internal_record_entry_t *internal_record_entry = NULL;
546 	static char *function                                 = "libpff_record_entry_set_value_data";
547 
548 	if( record_entry == NULL )
549 	{
550 		libcerror_error_set(
551 		 error,
552 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
553 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
554 		 "%s: invalid record entry.",
555 		 function );
556 
557 		return( -1 );
558 	}
559 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
560 
561 	if( internal_record_entry->value_data != NULL )
562 	{
563 		libcerror_error_set(
564 		 error,
565 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
566 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
567 		 "%s: invalid record entry - value data already set.",
568 		 function );
569 
570 		return( -1 );
571 	}
572 	if( value_data_size > (size_t) SSIZE_MAX )
573 	{
574 		libcerror_error_set(
575 		 error,
576 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
577 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
578 		 "%s: invalid value data size value exceeds maximum.",
579 		 function );
580 
581 		return( -1 );
582 	}
583 	if( value_data_size > 0 )
584 	{
585 		if( value_data == NULL )
586 		{
587 			libcerror_error_set(
588 			 error,
589 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
590 			 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
591 			 "%s: invalid value data.",
592 			 function );
593 
594 			goto on_error;
595 		}
596 		internal_record_entry->value_data = (uint8_t *) memory_allocate(
597 		                                                 value_data_size );
598 
599 		if( internal_record_entry->value_data == NULL )
600 		{
601 			libcerror_error_set(
602 			 error,
603 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
604 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
605 			 "%s: unable to create value data.",
606 			 function );
607 
608 			goto on_error;
609 		}
610 		if( memory_copy(
611 		     internal_record_entry->value_data,
612 		     value_data,
613 		     value_data_size ) == NULL )
614 		{
615 			libcerror_error_set(
616 			 error,
617 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
618 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
619 			 "%s: unable to copy value data.",
620 			 function );
621 
622 			goto on_error;
623 		}
624 		internal_record_entry->value_data_size = value_data_size;
625 	}
626 	return( 1 );
627 
628 on_error:
629 	if( internal_record_entry->value_data != NULL )
630 	{
631 		memory_free(
632 		 internal_record_entry->value_data );
633 
634 		internal_record_entry->value_data = NULL;
635 	}
636 	internal_record_entry->value_data_size = 0;
637 
638 	return( -1 );
639 }
640 
641 /* Sets the value data from the list in the record entry
642  * The function makes a local copy
643  * Returns 1 if successful or -1 on error
644  */
libpff_record_entry_set_value_data_from_list(libpff_record_entry_t * record_entry,libbfio_handle_t * file_io_handle,libfdata_list_t * value_data_list,libfcache_cache_t * value_data_cache,libcerror_error_t ** error)645 int libpff_record_entry_set_value_data_from_list(
646      libpff_record_entry_t *record_entry,
647      libbfio_handle_t *file_io_handle,
648      libfdata_list_t *value_data_list,
649      libfcache_cache_t *value_data_cache,
650      libcerror_error_t **error )
651 {
652 	libfdata_stream_t *value_data_stream = NULL;
653 	static char *function                = "libpff_record_entry_set_value_data_from_list";
654 
655 	if( libpff_descriptor_data_stream_initialize(
656 	     &value_data_stream,
657 	     value_data_list,
658 	     value_data_cache,
659 	     LIBPFF_DESCRIPTOR_DATA_STREAM_DATA_HANDLE_FLAG_NON_MANAGED,
660 	     error ) != 1 )
661 	{
662 		libcerror_error_set(
663 		 error,
664 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
665 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
666 		 "%s: unable to create descriptor data stream.",
667 		 function );
668 
669 		goto on_error;
670 	}
671 	if( libpff_record_entry_set_value_data_from_stream(
672 	     record_entry,
673 	     file_io_handle,
674 	     value_data_stream,
675 	     error ) != 1 )
676 	{
677 		libcerror_error_set(
678 		 error,
679 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
680 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
681 		 "%s: unable to set value data from stream.",
682 		 function );
683 
684 		goto on_error;
685 	}
686 	if( libfdata_stream_free(
687 	     &value_data_stream,
688 	     error ) != 1 )
689 	{
690 		libcerror_error_set(
691 		 error,
692 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
693 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
694 		 "%s: unable to free descriptor data stream.",
695 		 function );
696 
697 		goto on_error;
698 	}
699 	return( 1 );
700 
701 on_error:
702 	if( value_data_stream != NULL )
703 	{
704 		libfdata_stream_free(
705 		 &value_data_stream,
706 		 NULL );
707 	}
708 	return( -1 );
709 }
710 
711 /* Sets the value data from the stream in the record entry
712  * The function makes a local copy
713  * Returns 1 if successful or -1 on error
714  */
libpff_record_entry_set_value_data_from_stream(libpff_record_entry_t * record_entry,libbfio_handle_t * file_io_handle,libfdata_stream_t * value_data_stream,libcerror_error_t ** error)715 int libpff_record_entry_set_value_data_from_stream(
716      libpff_record_entry_t *record_entry,
717      libbfio_handle_t *file_io_handle,
718      libfdata_stream_t *value_data_stream,
719      libcerror_error_t **error )
720 {
721 	libpff_internal_record_entry_t *internal_record_entry = NULL;
722 	static char *function                                 = "libpff_record_entry_set_value_data_from_stream";
723 	size64_t value_data_size                              = 0;
724 	ssize_t read_count                                    = 0;
725 
726 	if( record_entry == NULL )
727 	{
728 		libcerror_error_set(
729 		 error,
730 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
731 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
732 		 "%s: invalid record entry.",
733 		 function );
734 
735 		return( -1 );
736 	}
737 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
738 
739 	if( internal_record_entry->value_data != NULL )
740 	{
741 		libcerror_error_set(
742 		 error,
743 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
744 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
745 		 "%s: invalid record entry - value data already set.",
746 		 function );
747 
748 		return( -1 );
749 	}
750 	if( libfdata_stream_get_size(
751 	     value_data_stream,
752 	     &value_data_size,
753 	     error ) != 1 )
754 	{
755 		libcerror_error_set(
756 		 error,
757 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
758 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
759 		 "%s: unable to retrieve value data stream size.",
760 		 function );
761 
762 		return( -1 );
763 	}
764 	if( value_data_size > (size64_t) SSIZE_MAX )
765 	{
766 		libcerror_error_set(
767 		 error,
768 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
769 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
770 		 "%s: invalid value data size value out of bounds.",
771 		 function );
772 
773 		return( -1 );
774 	}
775 	if( value_data_size > 0 )
776 	{
777 		if( libfdata_stream_seek_offset(
778 		     value_data_stream,
779 		     0,
780 		     SEEK_SET,
781 		     error ) == -1 )
782 		{
783 			libcerror_error_set(
784 			 error,
785 			 LIBCERROR_ERROR_DOMAIN_IO,
786 			 LIBCERROR_IO_ERROR_SEEK_FAILED,
787 			 "%s: unable to seek offset: 0 in value data stream.",
788 			 function );
789 
790 			goto on_error;
791 		}
792 		internal_record_entry->value_data = (uint8_t *) memory_allocate(
793 		                                                 (size_t) value_data_size );
794 
795 		if( internal_record_entry->value_data == NULL )
796 		{
797 			libcerror_error_set(
798 			 error,
799 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
800 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
801 			 "%s: unable to create value data.",
802 			 function );
803 
804 			goto on_error;
805 		}
806 		internal_record_entry->value_data_size = (size_t) value_data_size;
807 
808 		read_count = libfdata_stream_read_buffer(
809 			      value_data_stream,
810 			      (intptr_t *) file_io_handle,
811 			      internal_record_entry->value_data,
812 			      internal_record_entry->value_data_size,
813 			      0,
814 			      error );
815 
816 		if( read_count != (ssize_t) internal_record_entry->value_data_size )
817 		{
818 			libcerror_error_set(
819 			 error,
820 			 LIBCERROR_ERROR_DOMAIN_IO,
821 			 LIBCERROR_IO_ERROR_READ_FAILED,
822 			 "%s: unable to read buffer from value data stream.",
823 			 function );
824 
825 			goto on_error;
826 		}
827 	}
828 	return( 1 );
829 
830 on_error:
831 	if( internal_record_entry->value_data != NULL )
832 	{
833 		memory_free(
834 		 internal_record_entry->value_data );
835 
836 		internal_record_entry->value_data = NULL;
837 	}
838 	internal_record_entry->value_data_size = 0;
839 
840 	return( -1 );
841 }
842 
843 /* Retrieves the data
844  * Returns 1 if successful or -1 on error
845  */
libpff_record_entry_get_data(libpff_record_entry_t * record_entry,uint8_t * data,size_t data_size,libcerror_error_t ** error)846 int libpff_record_entry_get_data(
847      libpff_record_entry_t *record_entry,
848      uint8_t *data,
849      size_t data_size,
850      libcerror_error_t **error )
851 {
852 	libpff_internal_record_entry_t *internal_record_entry = NULL;
853 	static char *function                                 = "libpff_record_entry_get_data";
854 
855 	if( record_entry == NULL )
856 	{
857 		libcerror_error_set(
858 		 error,
859 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
860 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
861 		 "%s: invalid record entry.",
862 		 function );
863 
864 		return( -1 );
865 	}
866 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
867 
868 	if( internal_record_entry->value_data == NULL )
869 	{
870 		libcerror_error_set(
871 		 error,
872 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
873 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
874 		 "%s: invalid record entry - missing value data.",
875 		 function );
876 
877 		return( -1 );
878 	}
879 	if( data == NULL )
880 	{
881 		libcerror_error_set(
882 		 error,
883 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
884 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
885 		 "%s: invalid data.",
886 		 function );
887 
888 		return( -1 );
889 	}
890 	if( data_size > (size_t) SSIZE_MAX )
891 	{
892 		libcerror_error_set(
893 		 error,
894 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
895 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
896 		 "%s: invalid data size value exceeds maximum.",
897 		 function );
898 
899 		return( -1 );
900 	}
901 	if( data_size < internal_record_entry->value_data_size )
902 	{
903 		libcerror_error_set(
904 		 error,
905 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
906 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
907 		 "%s: invalid data value too small.",
908 		 function );
909 
910 		return( -1 );
911 	}
912 	if( memory_copy(
913 	     data,
914 	     internal_record_entry->value_data,
915 	     internal_record_entry->value_data_size ) == NULL )
916 	{
917 		libcerror_error_set(
918 		 error,
919 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
920 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
921 		 "%s: unable to copy value data.",
922 		 function );
923 
924 		return( -1 );
925 	}
926 	return( 1 );
927 }
928 
929 /* Retrieves the data as a boolean value
930  * Returns 1 if successful or -1 on error
931  */
libpff_record_entry_get_data_as_boolean(libpff_record_entry_t * record_entry,uint8_t * value_boolean,libcerror_error_t ** error)932 int libpff_record_entry_get_data_as_boolean(
933      libpff_record_entry_t *record_entry,
934      uint8_t *value_boolean,
935      libcerror_error_t **error )
936 {
937 	libpff_internal_record_entry_t *internal_record_entry = NULL;
938 	static char *function                                 = "libpff_record_entry_get_data_as_boolean";
939 
940 	if( record_entry == NULL )
941 	{
942 		libcerror_error_set(
943 		 error,
944 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
945 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
946 		 "%s: invalid record entry.",
947 		 function );
948 
949 		return( -1 );
950 	}
951 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
952 
953 	if( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_BOOLEAN )
954 	{
955 		libcerror_error_set(
956 		 error,
957 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
958 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
959 		 "%s: unsupported value type.",
960 		 function );
961 
962 		return( -1 );
963 	}
964 	if( internal_record_entry->value_data == NULL )
965 	{
966 		libcerror_error_set(
967 		 error,
968 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
969 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
970 		 "%s: invalid record entry - missing value data.",
971 		 function );
972 
973 		return( -1 );
974 	}
975 	if( internal_record_entry->value_data_size != 1 )
976 	{
977 		libcerror_error_set(
978 		 error,
979 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
980 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
981 		 "%s: unsupported value data size.",
982 		 function );
983 
984 		return( -1 );
985 	}
986 	if( value_boolean == NULL )
987 	{
988 		libcerror_error_set(
989 		 error,
990 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
991 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
992 		 "%s: invalid value boolean.",
993 		 function );
994 
995 		return( -1 );
996 	}
997 	*value_boolean = internal_record_entry->value_data[ 0 ];
998 
999 	return( 1 );
1000 }
1001 
1002 /* Retrieves the data as a 16-bit integer value
1003  * Returns 1 if successful or -1 on error
1004  */
libpff_record_entry_get_data_as_16bit_integer(libpff_record_entry_t * record_entry,uint16_t * value_16bit,libcerror_error_t ** error)1005 int libpff_record_entry_get_data_as_16bit_integer(
1006      libpff_record_entry_t *record_entry,
1007      uint16_t *value_16bit,
1008      libcerror_error_t **error )
1009 {
1010 	libpff_internal_record_entry_t *internal_record_entry = NULL;
1011 	static char *function                                 = "libpff_record_entry_get_data_as_16bit_integer";
1012 
1013 	if( record_entry == NULL )
1014 	{
1015 		libcerror_error_set(
1016 		 error,
1017 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1018 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1019 		 "%s: invalid record entry.",
1020 		 function );
1021 
1022 		return( -1 );
1023 	}
1024 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
1025 
1026 	if( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_INTEGER_16BIT_SIGNED )
1027 	{
1028 		libcerror_error_set(
1029 		 error,
1030 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1031 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1032 		 "%s: unsupported value type.",
1033 		 function );
1034 
1035 		return( -1 );
1036 	}
1037 	if( internal_record_entry->value_data == NULL )
1038 	{
1039 		libcerror_error_set(
1040 		 error,
1041 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1042 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1043 		 "%s: invalid record entry - missing value data.",
1044 		 function );
1045 
1046 		return( -1 );
1047 	}
1048 	if( internal_record_entry->value_data_size != 2 )
1049 	{
1050 		libcerror_error_set(
1051 		 error,
1052 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1053 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1054 		 "%s: unsupported value data size.",
1055 		 function );
1056 
1057 		return( -1 );
1058 	}
1059 	if( value_16bit == NULL )
1060 	{
1061 		libcerror_error_set(
1062 		 error,
1063 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1064 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1065 		 "%s: invalid value 16-bit.",
1066 		 function );
1067 
1068 		return( -1 );
1069 	}
1070 	byte_stream_copy_to_uint16_little_endian(
1071 	 internal_record_entry->value_data,
1072 	 *value_16bit );
1073 
1074 	return( 1 );
1075 }
1076 
1077 /* Retrieves the data as a 32-bit integer value
1078  * Returns 1 if successful or -1 on error
1079  */
libpff_record_entry_get_data_as_32bit_integer(libpff_record_entry_t * record_entry,uint32_t * value_32bit,libcerror_error_t ** error)1080 int libpff_record_entry_get_data_as_32bit_integer(
1081      libpff_record_entry_t *record_entry,
1082      uint32_t *value_32bit,
1083      libcerror_error_t **error )
1084 {
1085 	libpff_internal_record_entry_t *internal_record_entry = NULL;
1086 	static char *function                                 = "libpff_record_entry_get_data_as_32bit_integer";
1087 
1088 	if( record_entry == NULL )
1089 	{
1090 		libcerror_error_set(
1091 		 error,
1092 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1093 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1094 		 "%s: invalid record entry.",
1095 		 function );
1096 
1097 		return( -1 );
1098 	}
1099 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
1100 
1101 	if( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_INTEGER_32BIT_SIGNED )
1102 	{
1103 		libcerror_error_set(
1104 		 error,
1105 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1106 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1107 		 "%s: unsupported value type.",
1108 		 function );
1109 
1110 		return( -1 );
1111 	}
1112 	if( internal_record_entry->value_data == NULL )
1113 	{
1114 		libcerror_error_set(
1115 		 error,
1116 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1117 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1118 		 "%s: invalid record entry - missing value data.",
1119 		 function );
1120 
1121 		return( -1 );
1122 	}
1123 	if( internal_record_entry->value_data_size != 4 )
1124 	{
1125 		libcerror_error_set(
1126 		 error,
1127 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1128 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1129 		 "%s: unsupported value data size.",
1130 		 function );
1131 
1132 		return( -1 );
1133 	}
1134 	if( value_32bit == NULL )
1135 	{
1136 		libcerror_error_set(
1137 		 error,
1138 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1139 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1140 		 "%s: invalid value 32-bit.",
1141 		 function );
1142 
1143 		return( -1 );
1144 	}
1145 	byte_stream_copy_to_uint32_little_endian(
1146 	 internal_record_entry->value_data,
1147 	 *value_32bit );
1148 
1149 	return( 1 );
1150 }
1151 
1152 /* Retrieves the data as a 64-bit integer value
1153  * Returns 1 if successful or -1 on error
1154  */
libpff_record_entry_get_data_as_64bit_integer(libpff_record_entry_t * record_entry,uint64_t * value_64bit,libcerror_error_t ** error)1155 int libpff_record_entry_get_data_as_64bit_integer(
1156      libpff_record_entry_t *record_entry,
1157      uint64_t *value_64bit,
1158      libcerror_error_t **error )
1159 {
1160 	libpff_internal_record_entry_t *internal_record_entry = NULL;
1161 	static char *function                                 = "libpff_record_entry_get_data_as_64bit_integer";
1162 
1163 	if( record_entry == NULL )
1164 	{
1165 		libcerror_error_set(
1166 		 error,
1167 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1168 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1169 		 "%s: invalid record entry.",
1170 		 function );
1171 
1172 		return( -1 );
1173 	}
1174 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
1175 
1176 	if( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_INTEGER_64BIT_SIGNED )
1177 	{
1178 		libcerror_error_set(
1179 		 error,
1180 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1181 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1182 		 "%s: unsupported value type.",
1183 		 function );
1184 
1185 		return( -1 );
1186 	}
1187 	if( internal_record_entry->value_data == NULL )
1188 	{
1189 		libcerror_error_set(
1190 		 error,
1191 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1192 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1193 		 "%s: invalid record entry - missing value data.",
1194 		 function );
1195 
1196 		return( -1 );
1197 	}
1198 	if( internal_record_entry->value_data_size != 8 )
1199 	{
1200 		libcerror_error_set(
1201 		 error,
1202 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1203 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1204 		 "%s: unsupported value data size.",
1205 		 function );
1206 
1207 		return( -1 );
1208 	}
1209 	if( value_64bit == NULL )
1210 	{
1211 		libcerror_error_set(
1212 		 error,
1213 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1214 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1215 		 "%s: invalid value 64-bit.",
1216 		 function );
1217 
1218 		return( -1 );
1219 	}
1220 	byte_stream_copy_to_uint64_little_endian(
1221 	 internal_record_entry->value_data,
1222 	 *value_64bit );
1223 
1224 	return( 1 );
1225 }
1226 
1227 /* Retrieves the data as a 64-bit FILETIME value
1228  * Returns 1 if successful or -1 on error
1229  */
libpff_record_entry_get_data_as_filetime(libpff_record_entry_t * record_entry,uint64_t * filetime,libcerror_error_t ** error)1230 int libpff_record_entry_get_data_as_filetime(
1231      libpff_record_entry_t *record_entry,
1232      uint64_t *filetime,
1233      libcerror_error_t **error )
1234 {
1235 	libpff_internal_record_entry_t *internal_record_entry = NULL;
1236 	static char *function                                 = "libpff_record_entry_get_data_as_filetime";
1237 
1238 	if( record_entry == NULL )
1239 	{
1240 		libcerror_error_set(
1241 		 error,
1242 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1243 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1244 		 "%s: invalid record entry.",
1245 		 function );
1246 
1247 		return( -1 );
1248 	}
1249 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
1250 
1251 	if( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_FILETIME )
1252 	{
1253 		libcerror_error_set(
1254 		 error,
1255 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1256 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1257 		 "%s: unsupported value type.",
1258 		 function );
1259 
1260 		return( -1 );
1261 	}
1262 	if( internal_record_entry->value_data == NULL )
1263 	{
1264 		libcerror_error_set(
1265 		 error,
1266 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1267 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1268 		 "%s: invalid record entry - missing value data.",
1269 		 function );
1270 
1271 		return( -1 );
1272 	}
1273 	if( internal_record_entry->value_data_size != 8 )
1274 	{
1275 		libcerror_error_set(
1276 		 error,
1277 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1278 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1279 		 "%s: unsupported value data size.",
1280 		 function );
1281 
1282 		return( -1 );
1283 	}
1284 	if( filetime == NULL )
1285 	{
1286 		libcerror_error_set(
1287 		 error,
1288 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1289 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1290 		 "%s: invalid filetime.",
1291 		 function );
1292 
1293 		return( -1 );
1294 	}
1295 	byte_stream_copy_to_uint64_little_endian(
1296 	 internal_record_entry->value_data,
1297 	 *filetime );
1298 
1299 	return( 1 );
1300 }
1301 
1302 /* Retrieves the data as a 64-bit floatingtime value
1303  * Returns 1 if successful or -1 on error
1304  */
libpff_record_entry_get_data_as_floatingtime(libpff_record_entry_t * record_entry,uint64_t * floatingtime,libcerror_error_t ** error)1305 int libpff_record_entry_get_data_as_floatingtime(
1306      libpff_record_entry_t *record_entry,
1307      uint64_t *floatingtime,
1308      libcerror_error_t **error )
1309 {
1310 	libpff_internal_record_entry_t *internal_record_entry = NULL;
1311 	static char *function                                 = "libpff_record_entry_get_data_as_floatingtime";
1312 
1313 	if( record_entry == NULL )
1314 	{
1315 		libcerror_error_set(
1316 		 error,
1317 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1318 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1319 		 "%s: invalid record entry.",
1320 		 function );
1321 
1322 		return( -1 );
1323 	}
1324 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
1325 
1326 	if( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_FLOATINGTIME )
1327 	{
1328 		libcerror_error_set(
1329 		 error,
1330 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1331 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1332 		 "%s: unsupported value type.",
1333 		 function );
1334 
1335 		return( -1 );
1336 	}
1337 	if( internal_record_entry->value_data == NULL )
1338 	{
1339 		libcerror_error_set(
1340 		 error,
1341 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1342 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1343 		 "%s: invalid record entry - missing value data.",
1344 		 function );
1345 
1346 		return( -1 );
1347 	}
1348 	if( internal_record_entry->value_data_size != 8 )
1349 	{
1350 		libcerror_error_set(
1351 		 error,
1352 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1353 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1354 		 "%s: unsupported value data size.",
1355 		 function );
1356 
1357 		return( -1 );
1358 	}
1359 	if( floatingtime == NULL )
1360 	{
1361 		libcerror_error_set(
1362 		 error,
1363 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1364 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1365 		 "%s: invalid floatingtime.",
1366 		 function );
1367 
1368 		return( -1 );
1369 	}
1370 	byte_stream_copy_to_uint64_little_endian(
1371 	 internal_record_entry->value_data,
1372 	 *floatingtime );
1373 
1374 	return( 1 );
1375 }
1376 
1377 /* Retrieves the data as a size value
1378  * Returns 1 if successful or -1 on error
1379  */
libpff_record_entry_get_data_as_size(libpff_record_entry_t * record_entry,size64_t * value_size,libcerror_error_t ** error)1380 int libpff_record_entry_get_data_as_size(
1381      libpff_record_entry_t *record_entry,
1382      size64_t *value_size,
1383      libcerror_error_t **error )
1384 {
1385 	libpff_internal_record_entry_t *internal_record_entry = NULL;
1386 	static char *function                                 = "libpff_record_entry_get_data_as_size";
1387 
1388 	if( record_entry == NULL )
1389 	{
1390 		libcerror_error_set(
1391 		 error,
1392 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1393 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1394 		 "%s: invalid record entry.",
1395 		 function );
1396 
1397 		return( -1 );
1398 	}
1399 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
1400 
1401 	if( ( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_INTEGER_32BIT_SIGNED )
1402 	 && ( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_INTEGER_64BIT_SIGNED ) )
1403 	{
1404 		libcerror_error_set(
1405 		 error,
1406 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1407 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1408 		 "%s: unsupported value type.",
1409 		 function );
1410 
1411 		return( -1 );
1412 	}
1413 	if( internal_record_entry->value_data == NULL )
1414 	{
1415 		libcerror_error_set(
1416 		 error,
1417 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1418 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1419 		 "%s: invalid record entry - missing value data.",
1420 		 function );
1421 
1422 		return( -1 );
1423 	}
1424 	if( value_size == NULL )
1425 	{
1426 		libcerror_error_set(
1427 		 error,
1428 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1429 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1430 		 "%s: invalid value size.",
1431 		 function );
1432 
1433 		return( -1 );
1434 	}
1435 	if( ( internal_record_entry->value_data_size != 4 )
1436 	 && ( internal_record_entry->value_data_size != 8 ) )
1437 	{
1438 		libcerror_error_set(
1439 		 error,
1440 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1441 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1442 		 "%s: unsupported value data size.",
1443 		 function );
1444 
1445 		return( -1 );
1446 	}
1447 	if( internal_record_entry->value_data_size == 4 )
1448 	{
1449 		byte_stream_copy_to_uint32_little_endian(
1450 		 internal_record_entry->value_data,
1451 		 *value_size );
1452 	}
1453 	else if( internal_record_entry->value_data_size == 8 )
1454 	{
1455 		byte_stream_copy_to_uint64_little_endian(
1456 		 internal_record_entry->value_data,
1457 		 *value_size );
1458 	}
1459 	return( 1 );
1460 }
1461 
1462 /* Retrieves the data as a floating point value
1463  * Returns 1 if successful or -1 on error
1464  */
libpff_record_entry_get_data_as_floating_point(libpff_record_entry_t * record_entry,double * value_floating_point,libcerror_error_t ** error)1465 int libpff_record_entry_get_data_as_floating_point(
1466      libpff_record_entry_t *record_entry,
1467      double *value_floating_point,
1468      libcerror_error_t **error )
1469 {
1470 	byte_stream_float64_t value_double;
1471 	byte_stream_float32_t value_float;
1472 
1473 	libpff_internal_record_entry_t *internal_record_entry = NULL;
1474 	static char *function                                 = "libpff_record_entry_get_data_as_floating_point";
1475 
1476 	if( record_entry == NULL )
1477 	{
1478 		libcerror_error_set(
1479 		 error,
1480 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1481 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1482 		 "%s: invalid record entry.",
1483 		 function );
1484 
1485 		return( -1 );
1486 	}
1487 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
1488 
1489 	if( ( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_FLOAT_32BIT )
1490 	 && ( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_DOUBLE_64BIT ) )
1491 	{
1492 		libcerror_error_set(
1493 		 error,
1494 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1495 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1496 		 "%s: unsupported value type.",
1497 		 function );
1498 
1499 		return( -1 );
1500 	}
1501 	if( internal_record_entry->value_data == NULL )
1502 	{
1503 		libcerror_error_set(
1504 		 error,
1505 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1506 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1507 		 "%s: invalid record entry - missing value data.",
1508 		 function );
1509 
1510 		return( -1 );
1511 	}
1512 	if( value_floating_point == NULL )
1513 	{
1514 		libcerror_error_set(
1515 		 error,
1516 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1517 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1518 		 "%s: invalid value floating point.",
1519 		 function );
1520 
1521 		return( -1 );
1522 	}
1523 	if( ( internal_record_entry->value_data_size != 4 )
1524 	 && ( internal_record_entry->value_data_size != 8 ) )
1525 	{
1526 		libcerror_error_set(
1527 		 error,
1528 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1529 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1530 		 "%s: unsupported value data size.",
1531 		 function );
1532 
1533 		return( -1 );
1534 	}
1535 	if( internal_record_entry->value_data_size == 4 )
1536 	{
1537 		byte_stream_copy_to_uint32_little_endian(
1538 		 internal_record_entry->value_data,
1539 		 value_float.integer );
1540 
1541 		*value_floating_point = (double) value_float.floating_point;
1542 	}
1543 	else if( internal_record_entry->value_data_size == 8 )
1544 	{
1545 		byte_stream_copy_to_uint64_little_endian(
1546 		 internal_record_entry->value_data,
1547 		 value_double.integer );
1548 
1549 		*value_floating_point = value_double.floating_point;
1550 	}
1551 	return( 1 );
1552 }
1553 
1554 /* Retrieves the UTF-8 string size
1555  * The returned size includes the end of string character
1556  * Returns 1 if successful or -1 on error
1557  */
libpff_record_entry_get_data_as_utf8_string_size_with_codepage(libpff_record_entry_t * record_entry,int ascii_codepage,size_t * utf8_string_size,libcerror_error_t ** error)1558 int libpff_record_entry_get_data_as_utf8_string_size_with_codepage(
1559      libpff_record_entry_t *record_entry,
1560      int ascii_codepage,
1561      size_t *utf8_string_size,
1562      libcerror_error_t **error )
1563 {
1564 	libpff_internal_record_entry_t *internal_record_entry = NULL;
1565 	static char *function                                 = "libpff_record_entry_get_data_as_utf8_string_size_with_codepage";
1566 
1567 	if( record_entry == NULL )
1568 	{
1569 		libcerror_error_set(
1570 		 error,
1571 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1572 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1573 		 "%s: invalid record entry.",
1574 		 function );
1575 
1576 		return( -1 );
1577 	}
1578 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
1579 
1580 	if( libpff_mapi_value_get_data_as_utf8_string_size(
1581 	     internal_record_entry->identifier.value_type,
1582 	     internal_record_entry->value_data,
1583 	     internal_record_entry->value_data_size,
1584 	     ascii_codepage,
1585 	     utf8_string_size,
1586 	     error ) != 1 )
1587 	{
1588 		libcerror_error_set(
1589 		 error,
1590 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1591 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1592 		 "%s: unable to determine size of value data as UTF-8 string.",
1593 		 function );
1594 
1595 		return( -1 );
1596 	}
1597 	return( 1 );
1598 }
1599 
1600 /* Retrieves the UTF-8 string value
1601  * The function uses a codepage if necessary, it uses the codepage set for the library
1602  * The size should include the end of string character
1603  * Returns 1 if successful or -1 on error
1604  */
libpff_record_entry_get_data_as_utf8_string_with_codepage(libpff_record_entry_t * record_entry,int ascii_codepage,uint8_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)1605 int libpff_record_entry_get_data_as_utf8_string_with_codepage(
1606      libpff_record_entry_t *record_entry,
1607      int ascii_codepage,
1608      uint8_t *utf8_string,
1609      size_t utf8_string_size,
1610      libcerror_error_t **error )
1611 {
1612 	libpff_internal_record_entry_t *internal_record_entry = NULL;
1613 	static char *function                                 = "libpff_record_entry_get_data_as_utf8_string_with_codepage";
1614 
1615 	if( record_entry == NULL )
1616 	{
1617 		libcerror_error_set(
1618 		 error,
1619 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1620 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1621 		 "%s: invalid record entry.",
1622 		 function );
1623 
1624 		return( -1 );
1625 	}
1626 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
1627 
1628 	if( libpff_mapi_value_get_data_as_utf8_string(
1629 	     internal_record_entry->identifier.value_type,
1630 	     internal_record_entry->value_data,
1631 	     internal_record_entry->value_data_size,
1632 	     ascii_codepage,
1633 	     utf8_string,
1634 	     utf8_string_size,
1635 	     error ) != 1 )
1636 	{
1637 		libcerror_error_set(
1638 		 error,
1639 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1640 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1641 		 "%s: unable to retrieve value data as UTF-8 string.",
1642 		 function );
1643 
1644 		return( -1 );
1645 	}
1646 	return( 1 );
1647 }
1648 
1649 /* Compares the value data with an UTF-8 string
1650  * Returns 1 if the strings are equal, 0 if not or -1 on error
1651  */
libpff_record_entry_compare_value_with_utf8_string_with_codepage(libpff_record_entry_t * record_entry,int ascii_codepage,const uint8_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)1652 int libpff_record_entry_compare_value_with_utf8_string_with_codepage(
1653      libpff_record_entry_t *record_entry,
1654      int ascii_codepage,
1655      const uint8_t *utf8_string,
1656      size_t utf8_string_size,
1657      libcerror_error_t **error )
1658 {
1659 	libpff_internal_record_entry_t *internal_record_entry = NULL;
1660 	static char *function                                 = "libpff_record_entry_compare_value_with_utf8_string_with_codepage";
1661 	uint8_t is_ascii_string                               = 0;
1662 	int result                                            = 0;
1663 
1664 	if( record_entry == NULL )
1665 	{
1666 		libcerror_error_set(
1667 		 error,
1668 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1669 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1670 		 "%s: invalid record entry.",
1671 		 function );
1672 
1673 		return( -1 );
1674 	}
1675 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
1676 
1677 	if( utf8_string == NULL )
1678 	{
1679 		libcerror_error_set(
1680 		 error,
1681 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1682 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1683 		 "%s: invalid UTF-8 string.",
1684 		 function );
1685 
1686 		return( -1 );
1687 	}
1688 	if( utf8_string_size == 0 )
1689 	{
1690 		libcerror_error_set(
1691 		 error,
1692 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1693 		 LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
1694 		 "%s: invalid UTF-8 string size value zero or less.",
1695 		 function );
1696 
1697 		return( -1 );
1698 	}
1699 	if( utf8_string_size > (size_t) SSIZE_MAX )
1700 	{
1701 		libcerror_error_set(
1702 		 error,
1703 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1704 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1705 		 "%s: invalid UTF-8 string size value exceeds maximum.",
1706 		 function );
1707 
1708 		return( -1 );
1709 	}
1710 	if( ( internal_record_entry->value_data == NULL )
1711 	 || ( internal_record_entry->value_data_size == 0 ) )
1712 	{
1713 		return( 0 );
1714 	}
1715 	if( internal_record_entry->identifier.value_type == LIBPFF_VALUE_TYPE_STRING_ASCII )
1716 	{
1717 		is_ascii_string = 1;
1718 	}
1719 	/* Codepage 1200 represents Unicode
1720 	 * If the codepage is 1200 find out if the string is encoded in UTF-8 or UTF-16 little-endian
1721 	 */
1722 	if( ( is_ascii_string != 0 )
1723 	 && ( ascii_codepage == 1200 ) )
1724 	{
1725 		result = libpff_mapi_value_data_contains_zero_bytes(
1726 			  internal_record_entry->value_data,
1727 			  internal_record_entry->value_data_size,
1728 			  error );
1729 
1730 		if( result == -1 )
1731 		{
1732 			libcerror_error_set(
1733 			 error,
1734 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1735 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1736 			 "%s: unable to determine if value data contains zero bytes.",
1737 			 function );
1738 
1739 			return( -1 );
1740 		}
1741 		else if( result != 0 )
1742 		{
1743 			is_ascii_string = 0;
1744 		}
1745 	}
1746 	/* String is in UTF-16 little-endian
1747 	 */
1748 	if( is_ascii_string == 0 )
1749 	{
1750 		result = libuna_utf8_string_compare_with_utf16_stream(
1751 			  utf8_string,
1752 			  utf8_string_size,
1753 			  internal_record_entry->value_data,
1754 			  internal_record_entry->value_data_size,
1755 			  LIBUNA_ENDIAN_LITTLE,
1756 			  error );
1757 
1758 		if( result == -1 )
1759 		{
1760 			libcerror_error_set(
1761 			 error,
1762 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1763 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
1764 			 "%s: unable to compare UTF-8 string with UTF-16 stream.",
1765 			 function );
1766 
1767 			return( -1 );
1768 		}
1769 	}
1770 	/* Codepage 65000 represents UTF-7
1771 	 */
1772 	else if( ascii_codepage == 65000 )
1773 	{
1774 		result = libuna_utf8_string_compare_with_utf7_stream(
1775 			  utf8_string,
1776 			  utf8_string_size,
1777 			  internal_record_entry->value_data,
1778 			  internal_record_entry->value_data_size,
1779 			  error );
1780 
1781 		if( result == -1 )
1782 		{
1783 			libcerror_error_set(
1784 			 error,
1785 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1786 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
1787 			 "%s: unable to compare UTF-8 string with UTF-7 stream.",
1788 			 function );
1789 
1790 			return( -1 );
1791 		}
1792 	}
1793 	/* Codepage 1200 or 65001 represents UTF-8
1794 	 */
1795 	else if( ( ascii_codepage == 1200 )
1796 	      || ( ascii_codepage == 65001 ) )
1797 	{
1798 		result = libuna_utf8_string_compare_with_utf8_stream(
1799 			  utf8_string,
1800 			  utf8_string_size,
1801 			  internal_record_entry->value_data,
1802 			  internal_record_entry->value_data_size,
1803 			  error );
1804 
1805 		if( result == -1 )
1806 		{
1807 			libcerror_error_set(
1808 			 error,
1809 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1810 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
1811 			 "%s: unable to compare UTF-8 string with UTF-8 stream.",
1812 			 function );
1813 
1814 			return( -1 );
1815 		}
1816 	}
1817 	else
1818 	{
1819 		/* TODO currently libuna uses the same numeric values for the codepages as PFF
1820 		 * add a mapping function if this implementation changes
1821 		 */
1822 		result = libuna_utf8_string_compare_with_byte_stream(
1823 			  utf8_string,
1824 			  utf8_string_size,
1825 			  internal_record_entry->value_data,
1826 			  internal_record_entry->value_data_size,
1827 			  ascii_codepage,
1828 			  error );
1829 
1830 		if( result == -1 )
1831 		{
1832 			libcerror_error_set(
1833 			 error,
1834 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1835 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
1836 			 "%s: unable to compare UTF-8 string with byte stream.",
1837 			 function );
1838 
1839 			return( -1 );
1840 		}
1841 	}
1842 	return( result );
1843 }
1844 
1845 /* Retrieves the data formatted as an UTF-8 string
1846  * The returned size includes the end of string character
1847  * Returns 1 if successful or -1 on error
1848  */
libpff_record_entry_get_data_as_utf8_string_size(libpff_record_entry_t * record_entry,size_t * utf8_string_size,libcerror_error_t ** error)1849 int libpff_record_entry_get_data_as_utf8_string_size(
1850      libpff_record_entry_t *record_entry,
1851      size_t *utf8_string_size,
1852      libcerror_error_t **error )
1853 {
1854 	libpff_internal_record_entry_t *internal_record_entry = NULL;
1855 	static char *function                                 = "libpff_record_entry_get_data_as_utf8_string_size";
1856 
1857 	if( record_entry == NULL )
1858 	{
1859 		libcerror_error_set(
1860 		 error,
1861 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1862 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1863 		 "%s: invalid record entry.",
1864 		 function );
1865 
1866 		return( -1 );
1867 	}
1868 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
1869 
1870 	if( ( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_STRING_ASCII )
1871 	 && ( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_STRING_UNICODE ) )
1872 	{
1873 		libcerror_error_set(
1874 		 error,
1875 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1876 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1877 		 "%s: unsupported value type.",
1878 		 function );
1879 
1880 		return( -1 );
1881 	}
1882 	if( libpff_mapi_value_get_data_as_utf8_string_size(
1883 	     internal_record_entry->identifier.value_type,
1884 	     internal_record_entry->value_data,
1885 	     internal_record_entry->value_data_size,
1886 	     internal_record_entry->ascii_codepage,
1887 	     utf8_string_size,
1888 	     error ) != 1 )
1889 	{
1890 		libcerror_error_set(
1891 		 error,
1892 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1893 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1894 		 "%s: unable to determine size of value data as UTF-8 string.",
1895 		 function );
1896 
1897 		return( -1 );
1898 	}
1899 	return( 1 );
1900 }
1901 
1902 /* Retrieves the data formatted as an UTF-8 string
1903  * The function uses a codepage if necessary, it uses the codepage set for the library
1904  * The size should include the end of string character
1905  * Returns 1 if successful or -1 on error
1906  */
libpff_record_entry_get_data_as_utf8_string(libpff_record_entry_t * record_entry,uint8_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)1907 int libpff_record_entry_get_data_as_utf8_string(
1908      libpff_record_entry_t *record_entry,
1909      uint8_t *utf8_string,
1910      size_t utf8_string_size,
1911      libcerror_error_t **error )
1912 {
1913 	libpff_internal_record_entry_t *internal_record_entry = NULL;
1914 	static char *function                                 = "libpff_record_entry_get_data_as_utf8_string";
1915 
1916 	if( record_entry == NULL )
1917 	{
1918 		libcerror_error_set(
1919 		 error,
1920 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1921 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1922 		 "%s: invalid record entry.",
1923 		 function );
1924 
1925 		return( -1 );
1926 	}
1927 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
1928 
1929 	if( ( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_STRING_ASCII )
1930 	 && ( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_STRING_UNICODE ) )
1931 	{
1932 		libcerror_error_set(
1933 		 error,
1934 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1935 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1936 		 "%s: unsupported value type.",
1937 		 function );
1938 
1939 		return( -1 );
1940 	}
1941 	if( libpff_mapi_value_get_data_as_utf8_string(
1942 	     internal_record_entry->identifier.value_type,
1943 	     internal_record_entry->value_data,
1944 	     internal_record_entry->value_data_size,
1945 	     internal_record_entry->ascii_codepage,
1946 	     utf8_string,
1947 	     utf8_string_size,
1948 	     error ) != 1 )
1949 	{
1950 		libcerror_error_set(
1951 		 error,
1952 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1953 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1954 		 "%s: unable to retrieve value data as UTF-8 string.",
1955 		 function );
1956 
1957 		return( -1 );
1958 	}
1959 	return( 1 );
1960 }
1961 
1962 /* Retrieves the UTF-16 string size
1963  * The returned size includes the end of string character
1964  * Returns 1 if successful or -1 on error
1965  */
libpff_record_entry_get_data_as_utf16_string_size_with_codepage(libpff_record_entry_t * record_entry,int ascii_codepage,size_t * utf16_string_size,libcerror_error_t ** error)1966 int libpff_record_entry_get_data_as_utf16_string_size_with_codepage(
1967      libpff_record_entry_t *record_entry,
1968      int ascii_codepage,
1969      size_t *utf16_string_size,
1970      libcerror_error_t **error )
1971 {
1972 	libpff_internal_record_entry_t *internal_record_entry = NULL;
1973 	static char *function                                 = "libpff_record_entry_get_data_as_utf16_string_size_with_codepage";
1974 
1975 	if( record_entry == NULL )
1976 	{
1977 		libcerror_error_set(
1978 		 error,
1979 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1980 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1981 		 "%s: invalid record entry.",
1982 		 function );
1983 
1984 		return( -1 );
1985 	}
1986 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
1987 
1988 	if( libpff_mapi_value_get_data_as_utf16_string_size(
1989 	     internal_record_entry->identifier.value_type,
1990 	     internal_record_entry->value_data,
1991 	     internal_record_entry->value_data_size,
1992 	     ascii_codepage,
1993 	     utf16_string_size,
1994 	     error ) != 1 )
1995 	{
1996 		libcerror_error_set(
1997 		 error,
1998 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1999 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2000 		 "%s: unable to determine size of value data as UTF-16 string.",
2001 		 function );
2002 
2003 		return( -1 );
2004 	}
2005 	return( 1 );
2006 }
2007 
2008 /* Retrieves the UTF-16 string value
2009  * The function uses a codepage if necessary, it uses the codepage set for the library
2010  * The size should include the end of string character
2011  * Returns 1 if successful or -1 on error
2012  */
libpff_record_entry_get_data_as_utf16_string_with_codepage(libpff_record_entry_t * record_entry,int ascii_codepage,uint16_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)2013 int libpff_record_entry_get_data_as_utf16_string_with_codepage(
2014      libpff_record_entry_t *record_entry,
2015      int ascii_codepage,
2016      uint16_t *utf16_string,
2017      size_t utf16_string_size,
2018      libcerror_error_t **error )
2019 {
2020 	libpff_internal_record_entry_t *internal_record_entry = NULL;
2021 	static char *function                                 = "libpff_record_entry_get_data_as_utf16_string_with_codepage";
2022 
2023 	if( record_entry == NULL )
2024 	{
2025 		libcerror_error_set(
2026 		 error,
2027 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2028 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2029 		 "%s: invalid record entry.",
2030 		 function );
2031 
2032 		return( -1 );
2033 	}
2034 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
2035 
2036 	if( libpff_mapi_value_get_data_as_utf16_string(
2037 	     internal_record_entry->identifier.value_type,
2038 	     internal_record_entry->value_data,
2039 	     internal_record_entry->value_data_size,
2040 	     ascii_codepage,
2041 	     utf16_string,
2042 	     utf16_string_size,
2043 	     error ) != 1 )
2044 	{
2045 		libcerror_error_set(
2046 		 error,
2047 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2048 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2049 		 "%s: unable to retrieve value data as UTF-16 string.",
2050 		 function );
2051 
2052 		return( -1 );
2053 	}
2054 	return( 1 );
2055 }
2056 
2057 /* Compares the value data with an UTF-16 string
2058  * Returns 1 if the strings are equal, 0 if not or -1 on error
2059  */
libpff_record_entry_compare_value_with_utf16_string_with_codepage(libpff_record_entry_t * record_entry,int ascii_codepage,const uint16_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)2060 int libpff_record_entry_compare_value_with_utf16_string_with_codepage(
2061      libpff_record_entry_t *record_entry,
2062      int ascii_codepage,
2063      const uint16_t *utf16_string,
2064      size_t utf16_string_size,
2065      libcerror_error_t **error )
2066 {
2067 	libpff_internal_record_entry_t *internal_record_entry = NULL;
2068 	static char *function                                 = "libpff_record_entry_compare_value_with_utf16_string_with_codepage";
2069 	uint8_t is_ascii_string                               = 0;
2070 	int result                                            = 0;
2071 
2072 	if( record_entry == NULL )
2073 	{
2074 		libcerror_error_set(
2075 		 error,
2076 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2077 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2078 		 "%s: invalid record entry.",
2079 		 function );
2080 
2081 		return( -1 );
2082 	}
2083 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
2084 
2085 	if( utf16_string == NULL )
2086 	{
2087 		libcerror_error_set(
2088 		 error,
2089 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2090 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2091 		 "%s: invalid UTF-16 string.",
2092 		 function );
2093 
2094 		return( -1 );
2095 	}
2096 	if( utf16_string_size == 0 )
2097 	{
2098 		libcerror_error_set(
2099 		 error,
2100 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2101 		 LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
2102 		 "%s: invalid UTF-16 string size value zero or less.",
2103 		 function );
2104 
2105 		return( -1 );
2106 	}
2107 	if( utf16_string_size > (size_t) SSIZE_MAX )
2108 	{
2109 		libcerror_error_set(
2110 		 error,
2111 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2112 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2113 		 "%s: invalid UTF-16 string size value exceeds maximum.",
2114 		 function );
2115 
2116 		return( -1 );
2117 	}
2118 	if( ( internal_record_entry->value_data == NULL )
2119 	 || ( internal_record_entry->value_data_size == 0 ) )
2120 	{
2121 		return( 0 );
2122 	}
2123 	if( internal_record_entry->identifier.value_type == LIBPFF_VALUE_TYPE_STRING_ASCII )
2124 	{
2125 		is_ascii_string = 1;
2126 	}
2127 	/* Codepage 1200 represents Unicode
2128 	 * If the codepage is 1200 find out if the string is encoded in UTF-8 or UTF-16 little-endian
2129 	 */
2130 	if( ( is_ascii_string != 0 )
2131 	 && ( ascii_codepage == 1200 ) )
2132 	{
2133 		result = libpff_mapi_value_data_contains_zero_bytes(
2134 			  internal_record_entry->value_data,
2135 			  internal_record_entry->value_data_size,
2136 			  error );
2137 
2138 		if( result == -1 )
2139 		{
2140 			libcerror_error_set(
2141 			 error,
2142 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2143 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2144 			 "%s: unable to determine if value data contains zero bytes.",
2145 			 function );
2146 
2147 			return( -1 );
2148 		}
2149 		else if( result != 0 )
2150 		{
2151 			is_ascii_string = 0;
2152 		}
2153 	}
2154 	/* String is in UTF-16 little-endian
2155 	 */
2156 	if( is_ascii_string == 0 )
2157 	{
2158 		result = libuna_utf16_string_compare_with_utf16_stream(
2159 		          utf16_string,
2160 		          utf16_string_size,
2161 			  internal_record_entry->value_data,
2162 			  internal_record_entry->value_data_size,
2163 		          LIBUNA_ENDIAN_LITTLE,
2164 		          error );
2165 
2166 		if( result == -1 )
2167 		{
2168 			libcerror_error_set(
2169 			 error,
2170 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2171 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
2172 			 "%s: unable to compare UTF-16 string with UTF-16 stream.",
2173 			 function );
2174 
2175 			return( -1 );
2176 		}
2177 	}
2178 	/* Codepage 65000 represents UTF-7
2179 	 */
2180 	else if( ascii_codepage == 65000 )
2181 	{
2182 		result = libuna_utf16_string_compare_with_utf7_stream(
2183 			  utf16_string,
2184 			  utf16_string_size,
2185 			  internal_record_entry->value_data,
2186 			  internal_record_entry->value_data_size,
2187 			  error );
2188 
2189 		if( result == -1 )
2190 		{
2191 			libcerror_error_set(
2192 			 error,
2193 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2194 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
2195 			 "%s: unable to compare UTF-16 string with UTF-7 stream.",
2196 			 function );
2197 
2198 			return( -1 );
2199 		}
2200 	}
2201 	/* Codepage 1200 or 65001 represents UTF-8
2202 	 */
2203 	else if( ( ascii_codepage == 1200 )
2204 	      || ( ascii_codepage == 65001 ) )
2205 	{
2206 		result = libuna_utf16_string_compare_with_utf8_stream(
2207 			  utf16_string,
2208 			  utf16_string_size,
2209 			  internal_record_entry->value_data,
2210 			  internal_record_entry->value_data_size,
2211 			  error );
2212 
2213 		if( result == -1 )
2214 		{
2215 			libcerror_error_set(
2216 			 error,
2217 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2218 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
2219 			 "%s: unable to compare UTF-16 string with UTF-8 stream.",
2220 			 function );
2221 
2222 			return( -1 );
2223 		}
2224 	}
2225 	else
2226 	{
2227 		/* TODO currently libuna uses the same numeric values for the codepages as PFF
2228 		 * add a mapping function if this implementation changes
2229 		 */
2230 		result = libuna_utf16_string_compare_with_byte_stream(
2231 			  utf16_string,
2232 			  utf16_string_size,
2233 			  internal_record_entry->value_data,
2234 			  internal_record_entry->value_data_size,
2235 			  ascii_codepage,
2236 			  error );
2237 
2238 		if( result == -1 )
2239 		{
2240 			libcerror_error_set(
2241 			 error,
2242 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2243 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
2244 			 "%s: unable to compare UTF-16 string with byte stream.",
2245 			 function );
2246 
2247 			return( -1 );
2248 		}
2249 	}
2250 	return( result );
2251 }
2252 
2253 /* Retrieves the data formatted as an UTF-16 string
2254  * The returned size includes the end of string character
2255  * Returns 1 if successful or -1 on error
2256  */
libpff_record_entry_get_data_as_utf16_string_size(libpff_record_entry_t * record_entry,size_t * utf16_string_size,libcerror_error_t ** error)2257 int libpff_record_entry_get_data_as_utf16_string_size(
2258      libpff_record_entry_t *record_entry,
2259      size_t *utf16_string_size,
2260      libcerror_error_t **error )
2261 {
2262 	libpff_internal_record_entry_t *internal_record_entry = NULL;
2263 	static char *function                                 = "libpff_record_entry_get_data_as_utf16_string_size";
2264 
2265 	if( record_entry == NULL )
2266 	{
2267 		libcerror_error_set(
2268 		 error,
2269 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2270 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2271 		 "%s: invalid record entry.",
2272 		 function );
2273 
2274 		return( -1 );
2275 	}
2276 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
2277 
2278 	if( ( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_STRING_ASCII )
2279 	 && ( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_STRING_UNICODE ) )
2280 	{
2281 		libcerror_error_set(
2282 		 error,
2283 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2284 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2285 		 "%s: unsupported value type.",
2286 		 function );
2287 
2288 		return( -1 );
2289 	}
2290 	if( libpff_mapi_value_get_data_as_utf16_string_size(
2291 	     internal_record_entry->identifier.value_type,
2292 	     internal_record_entry->value_data,
2293 	     internal_record_entry->value_data_size,
2294 	     internal_record_entry->ascii_codepage,
2295 	     utf16_string_size,
2296 	     error ) != 1 )
2297 	{
2298 		libcerror_error_set(
2299 		 error,
2300 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2301 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2302 		 "%s: unable to determine size of value data as UTF-16 string.",
2303 		 function );
2304 
2305 		return( -1 );
2306 	}
2307 	return( 1 );
2308 }
2309 
2310 /* Retrieves the data formatted as an UTF-16 string
2311  * The function uses a codepage if necessary, it uses the codepage set for the library
2312  * The size should include the end of string character
2313  * Returns 1 if successful or -1 on error
2314  */
libpff_record_entry_get_data_as_utf16_string(libpff_record_entry_t * record_entry,uint16_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)2315 int libpff_record_entry_get_data_as_utf16_string(
2316      libpff_record_entry_t *record_entry,
2317      uint16_t *utf16_string,
2318      size_t utf16_string_size,
2319      libcerror_error_t **error )
2320 {
2321 	libpff_internal_record_entry_t *internal_record_entry = NULL;
2322 	static char *function                                 = "libpff_record_entry_get_data_as_utf16_string";
2323 
2324 	if( record_entry == NULL )
2325 	{
2326 		libcerror_error_set(
2327 		 error,
2328 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2329 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2330 		 "%s: invalid record entry.",
2331 		 function );
2332 
2333 		return( -1 );
2334 	}
2335 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
2336 
2337 	if( ( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_STRING_ASCII )
2338 	 && ( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_STRING_UNICODE ) )
2339 	{
2340 		libcerror_error_set(
2341 		 error,
2342 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2343 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2344 		 "%s: unsupported value type.",
2345 		 function );
2346 
2347 		return( -1 );
2348 	}
2349 	if( libpff_mapi_value_get_data_as_utf16_string(
2350 	     internal_record_entry->identifier.value_type,
2351 	     internal_record_entry->value_data,
2352 	     internal_record_entry->value_data_size,
2353 	     internal_record_entry->ascii_codepage,
2354 	     utf16_string,
2355 	     utf16_string_size,
2356 	     error ) != 1 )
2357 	{
2358 		libcerror_error_set(
2359 		 error,
2360 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2361 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2362 		 "%s: unable to retrieve value data as UTF-16 string.",
2363 		 function );
2364 
2365 		return( -1 );
2366 	}
2367 	return( 1 );
2368 }
2369 
2370 /* Retrieves the data as a GUID value
2371  * Returns 1 if successful or -1 on error
2372  */
libpff_record_entry_get_data_as_guid(libpff_record_entry_t * record_entry,uint8_t * guid_data,size_t guid_data_size,libcerror_error_t ** error)2373 int libpff_record_entry_get_data_as_guid(
2374      libpff_record_entry_t *record_entry,
2375      uint8_t *guid_data,
2376      size_t guid_data_size,
2377      libcerror_error_t **error )
2378 {
2379 	libpff_internal_record_entry_t *internal_record_entry = NULL;
2380 	static char *function                                 = "libpff_record_entry_get_data_as_guid";
2381 
2382 	if( record_entry == NULL )
2383 	{
2384 		libcerror_error_set(
2385 		 error,
2386 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2387 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2388 		 "%s: invalid record entry.",
2389 		 function );
2390 
2391 		return( -1 );
2392 	}
2393 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
2394 
2395 	if( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_GUID )
2396 	{
2397 		libcerror_error_set(
2398 		 error,
2399 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2400 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2401 		 "%s: invalid record entry - unsupported value type.",
2402 		 function );
2403 
2404 		return( -1 );
2405 	}
2406 	if( internal_record_entry->value_data == NULL )
2407 	{
2408 		libcerror_error_set(
2409 		 error,
2410 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2411 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2412 		 "%s: invalid record entry - missing value data.",
2413 		 function );
2414 
2415 		return( -1 );
2416 	}
2417 	if( internal_record_entry->value_data_size != 16 )
2418 	{
2419 		libcerror_error_set(
2420 		 error,
2421 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2422 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2423 		 "%s: unsupported value data size.",
2424 		 function );
2425 
2426 		return( -1 );
2427 	}
2428 	if( guid_data == NULL )
2429 	{
2430 		libcerror_error_set(
2431 		 error,
2432 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2433 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2434 		 "%s: invalid GUID data.",
2435 		 function );
2436 
2437 		return( -1 );
2438 	}
2439 	if( guid_data_size > (size_t) SSIZE_MAX )
2440 	{
2441 		libcerror_error_set(
2442 		 error,
2443 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2444 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2445 		 "%s: GUID data size value exceeds maximum.",
2446 		 function );
2447 
2448 		return( -1 );
2449 	}
2450 	if( guid_data_size < 16 )
2451 	{
2452 		libcerror_error_set(
2453 		 error,
2454 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2455 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2456 		 "%s: GUID data size value too small.",
2457 		 function );
2458 
2459 		return( -1 );
2460 	}
2461 	if( memory_copy(
2462 	     guid_data,
2463 	     internal_record_entry->value_data,
2464 	     16 ) == NULL )
2465 	{
2466 		libcerror_error_set(
2467 		 error,
2468 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
2469 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2470 		 "%s: unable to copy value data.",
2471 		 function );
2472 
2473 		return( -1 );
2474 	}
2475 	return( 1 );
2476 }
2477 
2478 /* Copies the value data to an object identifier
2479  * Returns 1 if successful or -1 on error
2480  */
libpff_record_entry_copy_object_identifier(libpff_record_entry_t * record_entry,uint32_t * object_identifier,libcerror_error_t ** error)2481 int libpff_record_entry_copy_object_identifier(
2482      libpff_record_entry_t *record_entry,
2483      uint32_t *object_identifier,
2484      libcerror_error_t **error )
2485 {
2486 	libpff_internal_record_entry_t *internal_record_entry = NULL;
2487 	static char *function                                 = "libpff_record_entry_copy_object_identifier";
2488 
2489 	if( record_entry == NULL )
2490 	{
2491 		libcerror_error_set(
2492 		 error,
2493 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2494 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2495 		 "%s: invalid record entry.",
2496 		 function );
2497 
2498 		return( -1 );
2499 	}
2500 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
2501 
2502 	if( internal_record_entry->identifier.value_type != LIBPFF_VALUE_TYPE_OBJECT )
2503 	{
2504 		libcerror_error_set(
2505 		 error,
2506 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2507 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2508 		 "%s: unsupported value type.",
2509 		 function );
2510 
2511 		return( -1 );
2512 	}
2513 	if( internal_record_entry->value_data == NULL )
2514 	{
2515 		libcerror_error_set(
2516 		 error,
2517 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2518 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2519 		 "%s: invalid record entry - missing value data.",
2520 		 function );
2521 
2522 		return( -1 );
2523 	}
2524 	if( object_identifier == NULL )
2525 	{
2526 		libcerror_error_set(
2527 		 error,
2528 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2529 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2530 		 "%s: invalid object identifier.",
2531 		 function );
2532 
2533 		return( -1 );
2534 	}
2535 	/* The value data size of an object is 8
2536 	 * where the first 4 bytes are the identifier
2537 	 */
2538 	if( internal_record_entry->value_data_size != 8 )
2539 	{
2540 		libcerror_error_set(
2541 		 error,
2542 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2543 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2544 		 "%s: unsupported value data size.",
2545 		 function );
2546 
2547 		return( -1 );
2548 	}
2549 	byte_stream_copy_to_uint32_little_endian(
2550 	 internal_record_entry->value_data,
2551 	 *object_identifier );
2552 
2553 	return( 1 );
2554 }
2555 
2556 /* Retrieves the multi value
2557  * Returns 1 if successful, 0 if not available or -1 on error
2558  */
libpff_record_entry_get_multi_value(libpff_record_entry_t * record_entry,libpff_multi_value_t ** multi_value,libcerror_error_t ** error)2559 int libpff_record_entry_get_multi_value(
2560      libpff_record_entry_t *record_entry,
2561      libpff_multi_value_t **multi_value,
2562      libcerror_error_t **error )
2563 {
2564 	libpff_internal_multi_value_t *internal_multi_value   = NULL;
2565 	libpff_internal_record_entry_t *internal_record_entry = NULL;
2566 	static char *function                                 = "libpff_record_entry_get_entry_value";
2567 	size_t value_size                                     = 0;
2568 	uint32_t number_of_values                             = 0;
2569 	uint32_t value_index                                  = 0;
2570 	uint32_t value_type                                   = 0;
2571 
2572 	if( record_entry == NULL )
2573 	{
2574 		libcerror_error_set(
2575 		 error,
2576 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2577 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2578 		 "%s: invalid record entry.",
2579 		 function );
2580 
2581 		return( -1 );
2582 	}
2583 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
2584 
2585 	if( multi_value == NULL )
2586 	{
2587 		libcerror_error_set(
2588 		 error,
2589 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2590 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2591 		 "%s: invalid multi value.",
2592 		 function );
2593 
2594 		return( -1 );
2595 	}
2596 	if( *multi_value != NULL )
2597 	{
2598 		libcerror_error_set(
2599 		 error,
2600 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2601 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2602 		 "%s: multi value already set.",
2603 		 function );
2604 
2605 		return( -1 );
2606 	}
2607 	if( ( internal_record_entry->value_data == NULL )
2608 	 || ( internal_record_entry->value_data_size == 0 ) )
2609 	{
2610 		return( 0 );
2611 	}
2612 	if( libpff_record_entry_get_value_type(
2613 	     record_entry,
2614 	     &value_type,
2615 	     error ) != 1 )
2616 	{
2617 		libcerror_error_set(
2618 		 error,
2619 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2620 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2621 		 "%s: unable to retrieve value type.",
2622 		 function );
2623 
2624 		goto on_error;
2625 	}
2626 	if( ( value_type & LIBPFF_VALUE_TYPE_MULTI_VALUE_FLAG ) == 0 )
2627 	{
2628 		libcerror_error_set(
2629 		 error,
2630 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2631 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2632 		 "%s: unsupported value type: 0x%04" PRIx32 ".",
2633 		 function,
2634 		 value_type );
2635 
2636 		goto on_error;
2637 	}
2638 	if( libpff_multi_value_initialize(
2639 	     multi_value,
2640 	     error ) != 1 )
2641 	{
2642 		libcerror_error_set(
2643 		 error,
2644 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2645 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2646 		 "%s: unable to create multi value.",
2647 		 function );
2648 
2649 		goto on_error;
2650 	}
2651 	internal_multi_value = (libpff_internal_multi_value_t *) *multi_value;
2652 
2653 	internal_multi_value->value_type = value_type;
2654 
2655 /* TODO is there a need to copy the multi value data ? use fvalue data handle instead ? */
2656 
2657 	/* Internally an empty multi value is represented by a NULL reference
2658 	 */
2659 	if( internal_record_entry->value_data != NULL )
2660 	{
2661 		internal_multi_value->value_data_size = internal_record_entry->value_data_size;
2662 
2663 		internal_multi_value->value_data = (uint8_t *) memory_allocate(
2664 								sizeof( uint8_t ) * internal_multi_value->value_data_size );
2665 
2666 		if( internal_multi_value->value_data == NULL )
2667 		{
2668 			libcerror_error_set(
2669 			 error,
2670 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
2671 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
2672 			 "%s: unable to create multi value data.",
2673 			 function );
2674 
2675 			goto on_error;
2676 		}
2677 		if( memory_copy(
2678 		     internal_multi_value->value_data,
2679 		     internal_record_entry->value_data,
2680 		     internal_multi_value->value_data_size ) == NULL )
2681 		{
2682 			libcerror_error_set(
2683 			 error,
2684 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
2685 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2686 			 "%s: unable to set multi value data.",
2687 			 function );
2688 
2689 			goto on_error;
2690 		}
2691 		switch( internal_multi_value->value_type )
2692 		{
2693 			case LIBPFF_VALUE_TYPE_MULTI_VALUE_INTEGER_16BIT_SIGNED:
2694 				value_size = 2;
2695 				break;
2696 
2697 			case LIBPFF_VALUE_TYPE_MULTI_VALUE_INTEGER_32BIT_SIGNED:
2698 				value_size = 4;
2699 				break;
2700 
2701 			case LIBPFF_VALUE_TYPE_MULTI_VALUE_INTEGER_64BIT_SIGNED:
2702 			case LIBPFF_VALUE_TYPE_MULTI_VALUE_FILETIME:
2703 				value_size = 8;
2704 				break;
2705 
2706 			case LIBPFF_VALUE_TYPE_MULTI_VALUE_GUID:
2707 				value_size = 16;
2708 				break;
2709 
2710 			case LIBPFF_VALUE_TYPE_MULTI_VALUE_STRING_ASCII:
2711 			case LIBPFF_VALUE_TYPE_MULTI_VALUE_STRING_UNICODE:
2712 			case LIBPFF_VALUE_TYPE_MULTI_VALUE_BINARY_DATA:
2713 				/* The first 4 bytes contain the number of values
2714 				 */
2715 				byte_stream_copy_from_uint32_little_endian(
2716 				 internal_record_entry->value_data,
2717 				 internal_multi_value->number_of_values );
2718 
2719 				break;
2720 
2721 			default:
2722 				libcerror_error_set(
2723 				 error,
2724 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2725 				 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2726 				 "%s: unsupported value type: 0x%04" PRIx32 ".",
2727 				 function,
2728 				 internal_multi_value->value_type );
2729 
2730 				goto on_error;
2731 		}
2732 		if( value_size != 0 )
2733 		{
2734 			if( ( internal_record_entry->value_data_size % value_size ) != 0 )
2735 			{
2736 				libcerror_error_set(
2737 				 error,
2738 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2739 				 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2740 				 "%s: value data size: %" PRIzd " not a multitude of value size: %" PRIzd ".",
2741 				 function,
2742 				 internal_record_entry->value_data_size,
2743 				 value_size );
2744 
2745 				goto on_error;
2746 			}
2747 			number_of_values = internal_record_entry->value_data_size / value_size;
2748 
2749 #if SIZE_MAX > UINT32_MAX
2750 			if( number_of_values > UINT32_MAX )
2751 			{
2752 				libcerror_error_set(
2753 				 error,
2754 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2755 				 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
2756 				 "%s: number of values value exceeds maximum.\n",
2757 				 function );
2758 
2759 				goto on_error;
2760 			}
2761 #endif
2762 			internal_multi_value->number_of_values = (uint32_t) number_of_values;
2763 		}
2764 		if( internal_multi_value->number_of_values > 0 )
2765 		{
2766 			internal_multi_value->value_offset = (uint32_t *) memory_allocate(
2767 									   sizeof( uint32_t ) * internal_multi_value->number_of_values );
2768 
2769 			if( internal_multi_value->value_offset == NULL )
2770 			{
2771 				libcerror_error_set(
2772 				 error,
2773 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
2774 				 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
2775 				 "%s: unable to create multi value offsets.",
2776 				 function );
2777 
2778 				goto on_error;
2779 			}
2780 			internal_multi_value->value_size = (size_t *) memory_allocate(
2781 								       sizeof( size_t ) * internal_multi_value->number_of_values );
2782 
2783 			if( internal_multi_value->value_offset == NULL )
2784 			{
2785 				libcerror_error_set(
2786 				 error,
2787 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
2788 				 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
2789 				 "%s: unable to create multi value offsets.",
2790 				 function );
2791 
2792 				goto on_error;
2793 			}
2794 			for( value_index = 0;
2795 			     value_index < internal_multi_value->number_of_values;
2796 			     value_index++ )
2797 			{
2798 				if( ( internal_multi_value->value_type == LIBPFF_VALUE_TYPE_MULTI_VALUE_STRING_ASCII )
2799 				 || ( internal_multi_value->value_type == LIBPFF_VALUE_TYPE_MULTI_VALUE_STRING_UNICODE )
2800 				 || ( internal_multi_value->value_type == LIBPFF_VALUE_TYPE_MULTI_VALUE_BINARY_DATA ) )
2801 				{
2802 					internal_record_entry->value_data += 4;
2803 
2804 					byte_stream_copy_to_uint32_little_endian(
2805 					 internal_record_entry->value_data,
2806 					 internal_multi_value->value_offset[ value_index ] );
2807 
2808 					if( internal_multi_value->value_offset[ value_index ] > internal_multi_value->value_data_size )
2809 					{
2810 						libcerror_error_set(
2811 						 error,
2812 						 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2813 						 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2814 						 "%s: value offset: %" PRIu32 " exceeds value data size: %" PRIzd ".",
2815 						 function,
2816 						 internal_multi_value->value_offset[ value_index ],
2817 						 internal_multi_value->value_data_size );
2818 
2819 						goto on_error;
2820 					}
2821 					if( value_index > 0 )
2822 					{
2823 						internal_multi_value->value_size[ value_index - 1 ] = internal_multi_value->value_offset[ value_index ]
2824 						                                                    - internal_multi_value->value_offset[ value_index - 1 ];
2825 					}
2826 				}
2827 				else
2828 				{
2829 					internal_multi_value->value_offset[ value_index ] = (uint32_t) ( value_index * value_size );
2830 					internal_multi_value->value_size[ value_index ]   = value_size;
2831 				}
2832 			}
2833 			if( ( internal_multi_value->value_type == LIBPFF_VALUE_TYPE_MULTI_VALUE_STRING_ASCII )
2834 			 || ( internal_multi_value->value_type == LIBPFF_VALUE_TYPE_MULTI_VALUE_STRING_UNICODE )
2835 			 || ( internal_multi_value->value_type == LIBPFF_VALUE_TYPE_MULTI_VALUE_BINARY_DATA ) )
2836 			{
2837 				internal_multi_value->value_size[ value_index - 1 ] = internal_multi_value->value_data_size
2838 				                                                    - internal_multi_value->value_offset[ value_index - 1 ];
2839 			}
2840 /* TODO refactor
2841 			internal_multi_value->ascii_codepage = ascii_codepage;
2842 */
2843 		}
2844 	}
2845 	return( 1 );
2846 
2847 on_error:
2848 	if( *multi_value != NULL )
2849 	{
2850 		libpff_multi_value_free(
2851 		 multi_value,
2852 		 NULL );
2853 	}
2854 	return( -1 );
2855 }
2856 
2857 /* Reads value data from the current offset into a buffer
2858  * Returns the number of bytes read or -1 on error
2859  */
libpff_record_entry_read_buffer(libpff_record_entry_t * record_entry,uint8_t * buffer,size_t buffer_size,libcerror_error_t ** error)2860 ssize_t libpff_record_entry_read_buffer(
2861          libpff_record_entry_t *record_entry,
2862          uint8_t *buffer,
2863          size_t buffer_size,
2864          libcerror_error_t **error )
2865 {
2866 	libpff_internal_record_entry_t *internal_record_entry = NULL;
2867 	static char *function                                 = "libpff_record_entry_read_buffer";
2868 
2869 	if( record_entry == NULL )
2870 	{
2871 		libcerror_error_set(
2872 		 error,
2873 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2874 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2875 		 "%s: invalid record entry.",
2876 		 function );
2877 
2878 		return( -1 );
2879 	}
2880 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
2881 
2882 	if( internal_record_entry->value_data_offset < 0 )
2883 	{
2884 		libcerror_error_set(
2885 		 error,
2886 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2887 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2888 		 "%s: invalid record entry - value data offset value out of bounds.",
2889 		 function );
2890 
2891 		return( -1 );
2892 	}
2893 	if( buffer == NULL )
2894 	{
2895 		libcerror_error_set(
2896 		 error,
2897 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2898 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2899 		 "%s: invalid buffer.",
2900 		 function );
2901 
2902 		return( -1 );
2903 	}
2904 	if( buffer_size > (size_t) SSIZE_MAX )
2905 	{
2906 		libcerror_error_set(
2907 		 error,
2908 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2909 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2910 		 "%s: invalid buffer size value exceeds maximum.",
2911 		 function );
2912 
2913 		return( -1 );
2914 	}
2915 	if( ( internal_record_entry->value_data == NULL )
2916 	 || ( internal_record_entry->value_data_offset >= (off64_t) internal_record_entry->value_data_size ) )
2917 	{
2918 		return( 0 );
2919 	}
2920 	if( ( buffer_size > internal_record_entry->value_data_size )
2921 	 || ( ( (size_t) internal_record_entry->value_data_offset + buffer_size ) > internal_record_entry->value_data_size ) )
2922 	{
2923 		buffer_size = (size_t) ( internal_record_entry->value_data_size - internal_record_entry->value_data_offset );
2924 	}
2925 	if( memory_copy(
2926 	     buffer,
2927 	     &( internal_record_entry->value_data[ internal_record_entry->value_data_offset ] ),
2928 	     buffer_size ) == NULL )
2929 	{
2930 		libcerror_error_set(
2931 		 error,
2932 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
2933 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2934 		 "%s: unable to copy value data to buffer.",
2935 		 function );
2936 
2937 		return( -1 );
2938 	}
2939 	internal_record_entry->value_data_offset += buffer_size;
2940 
2941 	return( (ssize_t) buffer_size );
2942 }
2943 
2944 /* Seeks a certain offset of the value data
2945  * Returns the offset if seek is successful or -1 on error
2946  */
libpff_record_entry_seek_offset(libpff_record_entry_t * record_entry,off64_t offset,int whence,libcerror_error_t ** error)2947 off64_t libpff_record_entry_seek_offset(
2948          libpff_record_entry_t *record_entry,
2949          off64_t offset,
2950          int whence,
2951          libcerror_error_t **error )
2952 {
2953 	libpff_internal_record_entry_t *internal_record_entry = NULL;
2954 	static char *function                                 = "libpff_record_entry_seek_offset";
2955 
2956 	if( record_entry == NULL )
2957 	{
2958 		libcerror_error_set(
2959 		 error,
2960 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2961 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2962 		 "%s: invalid record entry.",
2963 		 function );
2964 
2965 		return( -1 );
2966 	}
2967 	internal_record_entry = (libpff_internal_record_entry_t *) record_entry;
2968 
2969 	if( internal_record_entry->value_data_offset < 0 )
2970 	{
2971 		libcerror_error_set(
2972 		 error,
2973 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2974 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2975 		 "%s: invalid record entry - value data offset value out of bounds.",
2976 		 function );
2977 
2978 		return( -1 );
2979 	}
2980 	if( ( whence != SEEK_CUR )
2981 	 && ( whence != SEEK_END )
2982 	 && ( whence != SEEK_SET ) )
2983 	{
2984 		libcerror_error_set(
2985 		 error,
2986 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2987 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2988 		 "%s: unsupported whence.",
2989 		 function );
2990 
2991 		return( -1 );
2992 	}
2993 	if( whence == SEEK_CUR )
2994 	{
2995 		offset += internal_record_entry->value_data_offset;
2996 	}
2997 	else if( whence == SEEK_END )
2998 	{
2999 		offset += (off64_t) internal_record_entry->value_data_size;
3000 	}
3001 #if defined( HAVE_DEBUG_OUTPUT )
3002 	if( libcnotify_verbose != 0 )
3003 	{
3004 		libcnotify_printf(
3005 		 "%s: seeking offset: %" PRIi64 ".\n",
3006 		 function,
3007 		 offset );
3008 	}
3009 #endif
3010 	if( offset < 0 )
3011 	{
3012 		libcerror_error_set(
3013 		 error,
3014 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3015 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3016 		 "%s: offset value out of bounds.",
3017 		 function );
3018 
3019 		return( -1 );
3020 	}
3021 	internal_record_entry->value_data_offset = offset;
3022 
3023 	return( offset );
3024 }
3025 
3026