1 /*
2  * Attribute list entry functions
3  *
4  * Copyright (C) 2010-2021, Joachim Metz <joachim.metz@gmail.com>
5  *
6  * Refer to AUTHORS for acknowledgements.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <common.h>
23 #include <byte_stream.h>
24 #include <memory.h>
25 #include <types.h>
26 
27 #include "libfsntfs_debug.h"
28 #include "libfsntfs_libcdata.h"
29 #include "libfsntfs_libcerror.h"
30 #include "libfsntfs_libcnotify.h"
31 #include "libfsntfs_libuna.h"
32 #include "libfsntfs_mft_attribute_list_entry.h"
33 #include "libfsntfs_name.h"
34 
35 #include "fsntfs_mft_attribute_list.h"
36 
37 /* Creates attribute list entry
38  * Make sure the value attribute_list_entry is referencing, is set to NULL
39  * Returns 1 if successful or -1 on error
40  */
libfsntfs_mft_attribute_list_entry_initialize(libfsntfs_mft_attribute_list_entry_t ** attribute_list_entry,libcerror_error_t ** error)41 int libfsntfs_mft_attribute_list_entry_initialize(
42      libfsntfs_mft_attribute_list_entry_t **attribute_list_entry,
43      libcerror_error_t **error )
44 {
45 	static char *function = "libfsntfs_mft_attribute_list_entry_initialize";
46 
47 	if( attribute_list_entry == NULL )
48 	{
49 		libcerror_error_set(
50 		 error,
51 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
52 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
53 		 "%s: invalid attribute list entry.",
54 		 function );
55 
56 		return( -1 );
57 	}
58 	if( *attribute_list_entry != NULL )
59 	{
60 		libcerror_error_set(
61 		 error,
62 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
63 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
64 		 "%s: invalid attribute list entry value already set.",
65 		 function );
66 
67 		return( -1 );
68 	}
69 	*attribute_list_entry = memory_allocate_structure(
70 	                         libfsntfs_mft_attribute_list_entry_t );
71 
72 	if( *attribute_list_entry == NULL )
73 	{
74 		libcerror_error_set(
75 		 error,
76 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
77 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
78 		 "%s: unable to create attribute list entry.",
79 		 function );
80 
81 		goto on_error;
82 	}
83 	if( memory_set(
84 	     *attribute_list_entry,
85 	     0,
86 	     sizeof( libfsntfs_mft_attribute_list_entry_t ) ) == NULL )
87 	{
88 		libcerror_error_set(
89 		 error,
90 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
91 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
92 		 "%s: unable to clear attribute list entry.",
93 		 function );
94 
95 		goto on_error;
96 	}
97 	return( 1 );
98 
99 on_error:
100 	if( *attribute_list_entry != NULL )
101 	{
102 		memory_free(
103 		 *attribute_list_entry );
104 
105 		*attribute_list_entry = NULL;
106 	}
107 	return( -1 );
108 }
109 
110 /* Frees attribute list entry
111  * Returns 1 if successful or -1 on error
112  */
libfsntfs_mft_attribute_list_entry_free(libfsntfs_mft_attribute_list_entry_t ** attribute_list_entry,libcerror_error_t ** error)113 int libfsntfs_mft_attribute_list_entry_free(
114      libfsntfs_mft_attribute_list_entry_t **attribute_list_entry,
115      libcerror_error_t **error )
116 {
117 	static char *function = "libfsntfs_mft_attribute_list_entry_free";
118 
119 	if( attribute_list_entry == NULL )
120 	{
121 		libcerror_error_set(
122 		 error,
123 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
124 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
125 		 "%s: invalid attribute list entry.",
126 		 function );
127 
128 		return( -1 );
129 	}
130 	if( *attribute_list_entry != NULL )
131 	{
132 		if( ( *attribute_list_entry )->name != NULL )
133 		{
134 			memory_free(
135 			 ( *attribute_list_entry )->name );
136 		}
137 		memory_free(
138 		 *attribute_list_entry );
139 
140 		*attribute_list_entry = NULL;
141 	}
142 	return( 1 );
143 }
144 
145 /* Reads the attribute list entry
146  * Returns 1 if successful or -1 on error
147  */
libfsntfs_mft_attribute_list_entry_read_data(libfsntfs_mft_attribute_list_entry_t * attribute_list_entry,const uint8_t * data,size_t data_size,libcerror_error_t ** error)148 int libfsntfs_mft_attribute_list_entry_read_data(
149      libfsntfs_mft_attribute_list_entry_t *attribute_list_entry,
150      const uint8_t *data,
151      size_t data_size,
152      libcerror_error_t **error )
153 {
154 	static char *function = "libfsntfs_mft_attribute_list_entry_read_data";
155 	size_t data_offset    = 0;
156 	uint8_t name_offset   = 0;
157 
158 	if( attribute_list_entry == NULL )
159 	{
160 		libcerror_error_set(
161 		 error,
162 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
163 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
164 		 "%s: invalid attribute list entry.",
165 		 function );
166 
167 		return( -1 );
168 	}
169 	if( attribute_list_entry->name != NULL )
170 	{
171 		libcerror_error_set(
172 		 error,
173 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
174 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
175 		 "%s: invalid attribute list entry - name value already set.",
176 		 function );
177 
178 		return( -1 );
179 	}
180 	if( data == NULL )
181 	{
182 		libcerror_error_set(
183 		 error,
184 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
185 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
186 		 "%s: invalid data.",
187 		 function );
188 
189 		return( -1 );
190 	}
191 	if( data_size > (size_t) SSIZE_MAX )
192 	{
193 		libcerror_error_set(
194 		 error,
195 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
196 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
197 		 "%s: data size value exceeds maximum.",
198 		 function );
199 
200 		return( -1 );
201 	}
202 	if( data_size < sizeof( fsntfs_mft_attribute_list_entry_header_t ) )
203 	{
204 		libcerror_error_set(
205 		 error,
206 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
207 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
208 		 "%s: unsupported data size value too small.",
209 		 function );
210 
211 		return( -1 );
212 	}
213 #if defined( HAVE_DEBUG_OUTPUT )
214 	if( libcnotify_verbose != 0 )
215 	{
216 		libcnotify_printf(
217 		 "%s: attribute list entry header data:\n",
218 		 function );
219 		libcnotify_print_data(
220 		 data,
221 		 sizeof( fsntfs_mft_attribute_list_entry_header_t ),
222 		 0 );
223 	}
224 #endif
225 	byte_stream_copy_to_uint32_little_endian(
226 	 ( (fsntfs_mft_attribute_list_entry_header_t *) data )->type,
227 	 attribute_list_entry->attribute_type );
228 
229 	byte_stream_copy_to_uint16_little_endian(
230 	 ( (fsntfs_mft_attribute_list_entry_header_t *) data )->size,
231 	 attribute_list_entry->size );
232 
233 	attribute_list_entry->name_size = (uint16_t) ( (fsntfs_mft_attribute_list_entry_header_t *) data )->name_size;
234 
235 	name_offset = ( (fsntfs_mft_attribute_list_entry_header_t *) data )->name_offset;
236 
237 	byte_stream_copy_to_uint64_little_endian(
238 	 ( (fsntfs_mft_attribute_list_entry_header_t *) data )->data_first_vcn,
239 	 attribute_list_entry->data_first_vcn );
240 
241 	byte_stream_copy_to_uint64_little_endian(
242 	 ( (fsntfs_mft_attribute_list_entry_header_t *) data )->file_reference,
243 	 attribute_list_entry->file_reference );
244 
245 	byte_stream_copy_to_uint16_little_endian(
246 	 ( (fsntfs_mft_attribute_list_entry_header_t *) data )->identifier,
247 	 attribute_list_entry->identifier );
248 
249 #if defined( HAVE_DEBUG_OUTPUT )
250 	if( libcnotify_verbose != 0 )
251 	{
252 		libcnotify_printf(
253 		 "%s: type\t\t\t: 0x%08" PRIx32 " (%s)\n",
254 		 function,
255 		 attribute_list_entry->attribute_type,
256 		 libfsntfs_debug_print_attribute_type(
257 		  attribute_list_entry->attribute_type ) );
258 
259 		libcnotify_printf(
260 		 "%s: size\t\t\t: %" PRIu16 "\n",
261 		 function,
262 		 attribute_list_entry->size );
263 
264 		libcnotify_printf(
265 		 "%s: name size\t\t\t: %" PRIu16 "\n",
266 		 function,
267 		 attribute_list_entry->name_size );
268 
269 		libcnotify_printf(
270 		 "%s: name offset\t\t: %" PRIu8 "\n",
271 		 function,
272 		 name_offset );
273 
274 		libcnotify_printf(
275 		 "%s: data first VCN\t\t: %" PRIu64 "\n",
276 		 function,
277 		 attribute_list_entry->data_first_vcn );
278 
279 		libcnotify_printf(
280 		 "%s: file reference\t\t: %" PRIu64 "-%" PRIu64 "\n",
281 		 function,
282 		 attribute_list_entry->file_reference & 0xffffffffffffUL,
283 		 attribute_list_entry->file_reference >> 48 );
284 
285 		libcnotify_printf(
286 		 "%s: identifier\t\t: %" PRIu16 "\n",
287 		 function,
288 		 attribute_list_entry->identifier );
289 	}
290 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
291 
292 	data_offset = sizeof( fsntfs_mft_attribute_list_entry_header_t );
293 
294 	if( ( attribute_list_entry->size < sizeof( fsntfs_mft_attribute_list_entry_header_t ) )
295 	 || ( attribute_list_entry->size > data_size ) )
296 	{
297 		libcerror_error_set(
298 		 error,
299 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
300 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
301 		 "%s: size value out of bounds.",
302 		 function );
303 
304 		goto on_error;
305 	}
306 	attribute_list_entry->name_size *= 2;
307 
308 	if( attribute_list_entry->name_size > 0 )
309 	{
310 		if( ( name_offset < sizeof( fsntfs_mft_attribute_list_entry_header_t ) )
311 		 || ( name_offset >= attribute_list_entry->size ) )
312 		{
313 			libcerror_error_set(
314 			 error,
315 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
316 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
317 			 "%s: name offset value out of bounds.",
318 			 function );
319 
320 			goto on_error;
321 		}
322 #if defined( HAVE_DEBUG_OUTPUT )
323 		if( libcnotify_verbose != 0 )
324 		{
325 			if( data_offset < name_offset )
326 			{
327 				libcnotify_printf(
328 				 "%s: unknown data:\n",
329 				 function );
330 				libcnotify_print_data(
331 				 &( data[ data_offset ] ),
332 				 (size_t) name_offset - data_offset,
333 				 0 );
334 			}
335 		}
336 #endif
337 		if( attribute_list_entry->name_size > ( attribute_list_entry->size - name_offset ) )
338 		{
339 			libcerror_error_set(
340 			 error,
341 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
342 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
343 			 "%s: name size value out of bounds.",
344 			 function );
345 
346 			goto on_error;
347 		}
348 		data_offset = (size_t) name_offset;
349 
350 #if defined( HAVE_DEBUG_OUTPUT )
351 		if( libcnotify_verbose != 0 )
352 		{
353 			libcnotify_printf(
354 			 "%s: name data:\n",
355 			 function );
356 			libcnotify_print_data(
357 			 &( data[ data_offset ] ),
358 			 (size_t) attribute_list_entry->name_size,
359 			 0 );
360 		}
361 #endif
362 		attribute_list_entry->name = (uint8_t *) memory_allocate(
363 		                                          sizeof( uint8_t ) * (size_t) attribute_list_entry->name_size );
364 
365 		if( attribute_list_entry->name == NULL )
366 		{
367 			libcerror_error_set(
368 			 error,
369 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
370 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
371 			 "%s: unable to create name.",
372 			 function );
373 
374 			goto on_error;
375 		}
376 		if( memory_copy(
377 		     attribute_list_entry->name,
378 		     &( data[ data_offset ] ),
379 		     (size_t) attribute_list_entry->name_size ) == NULL )
380 		{
381 			libcerror_error_set(
382 			 error,
383 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
384 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
385 			 "%s: unable to copy name.",
386 			 function );
387 
388 			goto on_error;
389 		}
390 		data_offset += (size_t) attribute_list_entry->name_size;
391 
392 #if defined( HAVE_DEBUG_OUTPUT )
393 		if( libcnotify_verbose != 0 )
394 		{
395 			if( libfsntfs_debug_print_utf16_string_value(
396 			     function,
397 			     "name\t\t\t",
398 			     attribute_list_entry->name,
399 			     (size_t) attribute_list_entry->name_size,
400 			     LIBUNA_ENDIAN_LITTLE,
401 			     error ) != 1 )
402 			{
403 				libcerror_error_set(
404 				 error,
405 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
406 				 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
407 				 "%s: unable to print UTF-16 string value.",
408 				 function );
409 
410 				goto on_error;
411 			}
412 			libcnotify_printf(
413 			 "\n" );
414 		}
415 #endif
416 	}
417 #if defined( HAVE_DEBUG_OUTPUT )
418 	if( libcnotify_verbose != 0 )
419 	{
420 		if( data_offset < attribute_list_entry->size )
421 		{
422 			libcnotify_printf(
423 			 "%s: trailing data:\n",
424 			 function );
425 			libcnotify_print_data(
426 			 &( data[ data_offset ] ),
427 			 (size_t) attribute_list_entry->size - data_offset,
428 			 0 );
429 		}
430 		else
431 		{
432 			libcnotify_printf(
433 			 "\n" );
434 		}
435 	}
436 #endif
437 	return( 1 );
438 
439 on_error:
440 	if( attribute_list_entry->name != NULL )
441 	{
442 		memory_free(
443 		 attribute_list_entry->name );
444 
445 		attribute_list_entry->name = NULL;
446 	}
447 	attribute_list_entry->name_size = 0;
448 
449 	return( -1 );
450 }
451 
452 /* Retrieves the attribute type
453  * Returns 1 if successful or -1 on error
454  */
libfsntfs_mft_attribute_list_entry_get_attribute_type(libfsntfs_mft_attribute_list_entry_t * attribute_list_entry,uint32_t * attribute_type,libcerror_error_t ** error)455 int libfsntfs_mft_attribute_list_entry_get_attribute_type(
456      libfsntfs_mft_attribute_list_entry_t *attribute_list_entry,
457      uint32_t *attribute_type,
458      libcerror_error_t **error )
459 {
460 	static char *function = "libfsntfs_mft_attribute_list_entry_get_attribute_type";
461 
462 	if( attribute_list_entry == NULL )
463 	{
464 		libcerror_error_set(
465 		 error,
466 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
467 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
468 		 "%s: invalid attribute list entry.",
469 		 function );
470 
471 		return( -1 );
472 	}
473 	if( attribute_type == NULL )
474 	{
475 		libcerror_error_set(
476 		 error,
477 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
478 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
479 		 "%s: invalid attribute type.",
480 		 function );
481 
482 		return( -1 );
483 	}
484 	*attribute_type = attribute_list_entry->attribute_type;
485 
486 	return( 1 );
487 }
488 
489 /* Retrieves the file references as an MFT entry index and sequence number
490  * If the value sequence_number is NULL it will be ignored
491  * Returns 1 if successful or -1 on error
492  */
libfsntfs_mft_attribute_list_entry_get_file_reference(libfsntfs_mft_attribute_list_entry_t * attribute_list_entry,uint64_t * file_reference,libcerror_error_t ** error)493 int libfsntfs_mft_attribute_list_entry_get_file_reference(
494      libfsntfs_mft_attribute_list_entry_t *attribute_list_entry,
495      uint64_t *file_reference,
496      libcerror_error_t **error )
497 {
498 	static char *function = "libfsntfs_mft_attribute_list_entry_get_file_reference";
499 
500 	if( attribute_list_entry == NULL )
501 	{
502 		libcerror_error_set(
503 		 error,
504 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
505 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
506 		 "%s: invalid attribute list entry.",
507 		 function );
508 
509 		return( -1 );
510 	}
511 	if( file_reference == NULL )
512 	{
513 		libcerror_error_set(
514 		 error,
515 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
516 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
517 		 "%s: invalid file reference.",
518 		 function );
519 
520 		return( -1 );
521 	}
522 	*file_reference = attribute_list_entry->file_reference;
523 
524 	return( 1 );
525 }
526 
527 /* Retrieves the size of the UTF-8 encoded name
528  * The returned size includes the end of string character
529  * Returns 1 if successful or -1 on error
530  */
libfsntfs_mft_attribute_list_entry_get_utf8_name_size(libfsntfs_mft_attribute_list_entry_t * attribute_list_entry,size_t * utf8_string_size,libcerror_error_t ** error)531 int libfsntfs_mft_attribute_list_entry_get_utf8_name_size(
532      libfsntfs_mft_attribute_list_entry_t *attribute_list_entry,
533      size_t *utf8_string_size,
534      libcerror_error_t **error )
535 {
536 	static char *function = "libfsntfs_mft_attribute_list_entry_get_utf8_name_size";
537 
538 	if( attribute_list_entry == NULL )
539 	{
540 		libcerror_error_set(
541 		 error,
542 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
543 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
544 		 "%s: invalid attribute list entry.",
545 		 function );
546 
547 		return( -1 );
548 	}
549 	if( ( attribute_list_entry->name == NULL )
550 	 || ( attribute_list_entry->name_size == 0 ) )
551 	{
552 		if( utf8_string_size == NULL )
553 		{
554 			libcerror_error_set(
555 			 error,
556 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
557 			 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
558 			 "%s: invalid UTF-8 string size.",
559 			 function );
560 
561 			return( -1 );
562 		}
563 		*utf8_string_size = 0;
564 	}
565 	else
566 	{
567 		if( libuna_utf8_string_size_from_utf16_stream(
568 		     attribute_list_entry->name,
569 		     (size_t) attribute_list_entry->name_size,
570 		     LIBUNA_ENDIAN_LITTLE,
571 		     utf8_string_size,
572 		     error ) != 1 )
573 		{
574 			libcerror_error_set(
575 			 error,
576 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
577 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
578 			 "%s: unable to retrieve UTF-8 string size.",
579 			 function );
580 
581 			return( -1 );
582 		}
583 	}
584 	return( 1 );
585 }
586 
587 /* Retrieves the UTF-8 encoded name
588  * The size should include the end of string character
589  * Returns 1 if successful or -1 on error
590  */
libfsntfs_mft_attribute_list_entry_get_utf8_name(libfsntfs_mft_attribute_list_entry_t * attribute_list_entry,uint8_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)591 int libfsntfs_mft_attribute_list_entry_get_utf8_name(
592      libfsntfs_mft_attribute_list_entry_t *attribute_list_entry,
593      uint8_t *utf8_string,
594      size_t utf8_string_size,
595      libcerror_error_t **error )
596 {
597 	static char *function = "libfsntfs_mft_attribute_list_entry_get_utf8_name";
598 
599 	if( attribute_list_entry == NULL )
600 	{
601 		libcerror_error_set(
602 		 error,
603 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
604 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
605 		 "%s: invalid attribute list entry.",
606 		 function );
607 
608 		return( -1 );
609 	}
610 	if( attribute_list_entry->name == NULL )
611 	{
612 		libcerror_error_set(
613 		 error,
614 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
615 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
616 		 "%s: invalid attribute list entry - missing name.",
617 		 function );
618 
619 		return( -1 );
620 	}
621 	if( libuna_utf8_string_copy_from_utf16_stream(
622 	     utf8_string,
623 	     utf8_string_size,
624 	     attribute_list_entry->name,
625 	     (size_t) attribute_list_entry->name_size,
626 	     LIBUNA_ENDIAN_LITTLE,
627 	     error ) != 1 )
628 	{
629 		libcerror_error_set(
630 		 error,
631 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
632 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
633 		 "%s: unable to retrieve UTF-8 string.",
634 		 function );
635 
636 		return( -1 );
637 	}
638 	return( 1 );
639 }
640 
641 /* Retrieves the size of the UTF-16 encoded name
642  * The returned size includes the end of string character
643  * Returns 1 if successful or -1 on error
644  */
libfsntfs_mft_attribute_list_entry_get_utf16_name_size(libfsntfs_mft_attribute_list_entry_t * attribute_list_entry,size_t * utf16_string_size,libcerror_error_t ** error)645 int libfsntfs_mft_attribute_list_entry_get_utf16_name_size(
646      libfsntfs_mft_attribute_list_entry_t *attribute_list_entry,
647      size_t *utf16_string_size,
648      libcerror_error_t **error )
649 {
650 	static char *function = "libfsntfs_mft_attribute_list_entry_get_utf16_name_size";
651 
652 	if( attribute_list_entry == NULL )
653 	{
654 		libcerror_error_set(
655 		 error,
656 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
657 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
658 		 "%s: invalid attribute list entry.",
659 		 function );
660 
661 		return( -1 );
662 	}
663 	if( ( attribute_list_entry->name == NULL )
664 	 || ( attribute_list_entry->name_size == 0 ) )
665 	{
666 		if( utf16_string_size == NULL )
667 		{
668 			libcerror_error_set(
669 			 error,
670 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
671 			 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
672 			 "%s: invalid UTF-16 string size.",
673 			 function );
674 
675 			return( -1 );
676 		}
677 		*utf16_string_size = 0;
678 	}
679 	else
680 	{
681 		if( libuna_utf16_string_size_from_utf16_stream(
682 		     attribute_list_entry->name,
683 		     (size_t) attribute_list_entry->name_size,
684 		     LIBUNA_ENDIAN_LITTLE,
685 		     utf16_string_size,
686 		     error ) != 1 )
687 		{
688 			libcerror_error_set(
689 			 error,
690 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
691 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
692 			 "%s: unable to retrieve UTF-16 string size.",
693 			 function );
694 
695 			return( -1 );
696 		}
697 	}
698 	return( 1 );
699 }
700 
701 /* Retrieves the UTF-16 encoded name
702  * The size should include the end of string character
703  * Returns 1 if successful or -1 on error
704  */
libfsntfs_mft_attribute_list_entry_get_utf16_name(libfsntfs_mft_attribute_list_entry_t * attribute_list_entry,uint16_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)705 int libfsntfs_mft_attribute_list_entry_get_utf16_name(
706      libfsntfs_mft_attribute_list_entry_t *attribute_list_entry,
707      uint16_t *utf16_string,
708      size_t utf16_string_size,
709      libcerror_error_t **error )
710 {
711 	static char *function = "libfsntfs_mft_attribute_list_entry_get_utf16_name";
712 
713 	if( attribute_list_entry == NULL )
714 	{
715 		libcerror_error_set(
716 		 error,
717 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
718 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
719 		 "%s: invalid attribute list entry.",
720 		 function );
721 
722 		return( -1 );
723 	}
724 	if( attribute_list_entry->name == NULL )
725 	{
726 		libcerror_error_set(
727 		 error,
728 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
729 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
730 		 "%s: invalid attribute list entry - missing name.",
731 		 function );
732 
733 		return( -1 );
734 	}
735 	if( libuna_utf16_string_copy_from_utf16_stream(
736 	     utf16_string,
737 	     utf16_string_size,
738 	     attribute_list_entry->name,
739 	     (size_t) attribute_list_entry->name_size,
740 	     LIBUNA_ENDIAN_LITTLE,
741 	     error ) != 1 )
742 	{
743 		libcerror_error_set(
744 		 error,
745 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
746 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
747 		 "%s: unable to retrieve UTF-16 string.",
748 		 function );
749 
750 		return( -1 );
751 	}
752 	return( 1 );
753 }
754 
755 /* Compares the name with an UTF-8 encoded string
756  * Returns 1 if the strings are equal, 0 if not or -1 on error
757  */
libfsntfs_mft_attribute_list_entry_compare_name_with_utf8_string(libfsntfs_mft_attribute_list_entry_t * attribute_list_entry,const uint8_t * utf8_string,size_t utf8_string_length,libcerror_error_t ** error)758 int libfsntfs_mft_attribute_list_entry_compare_name_with_utf8_string(
759      libfsntfs_mft_attribute_list_entry_t *attribute_list_entry,
760      const uint8_t *utf8_string,
761      size_t utf8_string_length,
762      libcerror_error_t **error )
763 {
764 	static char *function = "libfsntfs_mft_attribute_list_entry_compare_name_with_utf8_string";
765 	int result            = 0;
766 
767 	if( attribute_list_entry == NULL )
768 	{
769 		libcerror_error_set(
770 		 error,
771 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
772 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
773 		 "%s: invalid MFT attribute.",
774 		 function );
775 
776 		return( -1 );
777 	}
778 	if( attribute_list_entry->name == NULL )
779 	{
780 		return( 0 );
781 	}
782 	result = libfsntfs_name_compare_with_utf8_string(
783 	          attribute_list_entry->name,
784 	          attribute_list_entry->name_size,
785 	          utf8_string,
786 	          utf8_string_length,
787 	          0,
788 	          error );
789 
790 	if( result == -1 )
791 	{
792 		libcerror_error_set(
793 		 error,
794 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
795 		 LIBCERROR_RUNTIME_ERROR_GENERIC,
796 		 "%s: unable to compare UTF-8 string with name.",
797 		 function );
798 
799 		return( -1 );
800 	}
801 	else if( result == LIBUNA_COMPARE_EQUAL )
802 	{
803 		return( 1 );
804 	}
805 	return( 0 );
806 }
807 
808 /* Compares the name with an UTF-16 encoded string
809  * Returns 1 if the strings are equal, 0 if not or -1 on error
810  */
libfsntfs_mft_attribute_list_entry_compare_name_with_utf16_string(libfsntfs_mft_attribute_list_entry_t * attribute_list_entry,const uint16_t * utf16_string,size_t utf16_string_length,libcerror_error_t ** error)811 int libfsntfs_mft_attribute_list_entry_compare_name_with_utf16_string(
812      libfsntfs_mft_attribute_list_entry_t *attribute_list_entry,
813      const uint16_t *utf16_string,
814      size_t utf16_string_length,
815      libcerror_error_t **error )
816 {
817 	static char *function = "libfsntfs_mft_attribute_list_entry_compare_name_with_utf16_string";
818 	int result            = 0;
819 
820 	if( attribute_list_entry == NULL )
821 	{
822 		libcerror_error_set(
823 		 error,
824 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
825 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
826 		 "%s: invalid MFT attribute.",
827 		 function );
828 
829 		return( -1 );
830 	}
831 	if( attribute_list_entry->name == NULL )
832 	{
833 		return( 0 );
834 	}
835 	result = libfsntfs_name_compare_with_utf16_string(
836 	          attribute_list_entry->name,
837 	          attribute_list_entry->name_size,
838 	          utf16_string,
839 	          utf16_string_length,
840 	          0,
841 	          error );
842 
843 	if( result == -1 )
844 	{
845 		libcerror_error_set(
846 		 error,
847 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
848 		 LIBCERROR_RUNTIME_ERROR_GENERIC,
849 		 "%s: unable to compare UTF-16 string with name.",
850 		 function );
851 
852 		return( -1 );
853 	}
854 	else if( result == LIBUNA_COMPARE_EQUAL )
855 	{
856 		return( 1 );
857 	}
858 	return( 0 );
859 }
860 
861