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