1 /*
2  * MTP storage device volume (shell item) values 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 "libfwsi_debug.h"
28 #include "libfwsi_libcerror.h"
29 #include "libfwsi_libcnotify.h"
30 #include "libfwsi_libfguid.h"
31 #include "libfwsi_libfole.h"
32 #include "libfwsi_libuna.h"
33 #include "libfwsi_mtp_volume_values.h"
34 
35 /* Creates MTP volume values
36  * Make sure the value mtp_volume_values is referencing, is set to NULL
37  * Returns 1 if successful or -1 on error
38  */
libfwsi_mtp_volume_values_initialize(libfwsi_mtp_volume_values_t ** mtp_volume_values,libcerror_error_t ** error)39 int libfwsi_mtp_volume_values_initialize(
40      libfwsi_mtp_volume_values_t **mtp_volume_values,
41      libcerror_error_t **error )
42 {
43 	static char *function = "libfwsi_mtp_volume_values_initialize";
44 
45 	if( mtp_volume_values == NULL )
46 	{
47 		libcerror_error_set(
48 		 error,
49 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
50 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
51 		 "%s: invalid MTP volume values.",
52 		 function );
53 
54 		return( -1 );
55 	}
56 	if( *mtp_volume_values != NULL )
57 	{
58 		libcerror_error_set(
59 		 error,
60 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
61 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
62 		 "%s: invalid MTP volume values value already set.",
63 		 function );
64 
65 		return( -1 );
66 	}
67 	*mtp_volume_values = memory_allocate_structure(
68 	                      libfwsi_mtp_volume_values_t );
69 
70 	if( *mtp_volume_values == NULL )
71 	{
72 		libcerror_error_set(
73 		 error,
74 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
75 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
76 		 "%s: unable to create MTP volume values.",
77 		 function );
78 
79 		goto on_error;
80 	}
81 	if( memory_set(
82 	     *mtp_volume_values,
83 	     0,
84 	     sizeof( libfwsi_mtp_volume_values_t ) ) == NULL )
85 	{
86 		libcerror_error_set(
87 		 error,
88 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
89 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
90 		 "%s: unable to clear MTP volume values.",
91 		 function );
92 
93 		goto on_error;
94 	}
95 	return( 1 );
96 
97 on_error:
98 	if( *mtp_volume_values != NULL )
99 	{
100 		memory_free(
101 		 *mtp_volume_values );
102 
103 		*mtp_volume_values = NULL;
104 	}
105 	return( -1 );
106 }
107 
108 /* Frees MTP volume values
109  * Returns 1 if successful or -1 on error
110  */
libfwsi_mtp_volume_values_free(libfwsi_mtp_volume_values_t ** mtp_volume_values,libcerror_error_t ** error)111 int libfwsi_mtp_volume_values_free(
112      libfwsi_mtp_volume_values_t **mtp_volume_values,
113      libcerror_error_t **error )
114 {
115 	static char *function = "libfwsi_mtp_volume_values_free";
116 
117 	if( mtp_volume_values == NULL )
118 	{
119 		libcerror_error_set(
120 		 error,
121 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
122 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
123 		 "%s: invalid MTP volume values.",
124 		 function );
125 
126 		return( -1 );
127 	}
128 	if( *mtp_volume_values != NULL )
129 	{
130 		memory_free(
131 		 *mtp_volume_values );
132 
133 		*mtp_volume_values = NULL;
134 	}
135 	return( 1 );
136 }
137 
138 /* Reads the MTP volume values
139  * Returns 1 if successful, 0 if not supported or -1 on error
140  */
libfwsi_mtp_volume_values_read_data(libfwsi_mtp_volume_values_t * mtp_volume_values,const uint8_t * data,size_t data_size,libcerror_error_t ** error)141 int libfwsi_mtp_volume_values_read_data(
142      libfwsi_mtp_volume_values_t *mtp_volume_values,
143      const uint8_t *data,
144      size_t data_size,
145      libcerror_error_t **error )
146 {
147 	static char *function            = "libfwsi_mtp_volume_values_read_data";
148 	size_t data_offset               = 0;
149 	uint32_t file_system_string_size = 0;
150 	uint32_t guid_string_index       = 0;
151 	uint32_t identifier_string_size  = 0;
152 	uint32_t name_string_size        = 0;
153 	uint32_t number_of_guid_strings  = 0;
154 	uint32_t number_of_properties    = 0;
155 	uint32_t property_index          = 0;
156 	uint32_t property_value_type     = 0;
157         uint32_t signature               = 0;
158 	uint32_t string_size             = 0;
159 	uint16_t item_data_size          = 0;
160 
161 #if defined( HAVE_DEBUG_OUTPUT )
162 	uint32_t value_32bit             = 0;
163 	uint16_t value_16bit             = 0;
164 #endif
165 
166 	if( mtp_volume_values == NULL )
167 	{
168 		libcerror_error_set(
169 		 error,
170 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
171 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
172 		 "%s: invalid MTP volume values.",
173 		 function );
174 
175 		return( -1 );
176 	}
177 	if( data == NULL )
178 	{
179 		libcerror_error_set(
180 		 error,
181 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
182 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
183 		 "%s: invalid data.",
184 		 function );
185 
186 		return( -1 );
187 	}
188 	if( data_size > (size_t) SSIZE_MAX )
189 	{
190 		libcerror_error_set(
191 		 error,
192 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
193 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
194 		 "%s: data size exceeds maximum.",
195 		 function );
196 
197 		return( -1 );
198 	}
199 	/* Do not try to parse unsupported data sizes
200 	 */
201 	if( data_size < 10 )
202 	{
203 		return( 0 );
204 	}
205 	/* Do not try to parse unsupported shell item signatures
206 	 */
207 	byte_stream_copy_to_uint32_little_endian(
208 	 &( data[ 6 ] ),
209 	 signature );
210 
211 	if( signature != 0x10312005UL )
212 	{
213 		return( 0 );
214 	}
215 	byte_stream_copy_to_uint32_little_endian(
216 	 &( data[ 4 ] ),
217 	 item_data_size );
218 
219 #if defined( HAVE_DEBUG_OUTPUT )
220 	if( libcnotify_verbose != 0 )
221 	{
222 		libcnotify_printf(
223 		 "%s: class type indicator\t\t\t: 0x%02" PRIx8 "\n",
224 		 function,
225 		 data[ 2 ] );
226 
227 		libcnotify_printf(
228 		 "%s: unknown1\t\t\t\t: 0x%02" PRIx8 "\n",
229 		 function,
230 		 data[ 3 ] );
231 
232 		libcnotify_printf(
233 		 "%s: data size\t\t\t\t: %" PRIu16 "\n",
234 		 function,
235 		 item_data_size );
236 
237 		libcnotify_printf(
238 		 "%s: signature\t\t\t\t: 0x%08" PRIx32 "\n",
239 		 function,
240 		 signature );
241 	}
242 #endif
243 	if( item_data_size == 0 )
244 	{
245 		return( 10 );
246 	}
247 	if( ( item_data_size < 44 )
248 	 && ( item_data_size > ( data_size - 10 ) ) )
249 	{
250 		libcerror_error_set(
251 		 error,
252 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
253 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
254 		 "%s: invalid data size value out of bounds.",
255 		 function );
256 
257 		return( -1 );
258 	}
259 	byte_stream_copy_to_uint32_little_endian(
260 	 &( data[ 38 ] ),
261 	 name_string_size );
262 
263 	byte_stream_copy_to_uint32_little_endian(
264 	 &( data[ 42 ] ),
265 	 identifier_string_size );
266 
267 	byte_stream_copy_to_uint32_little_endian(
268 	 &( data[ 46 ] ),
269 	 file_system_string_size );
270 
271 	byte_stream_copy_to_uint32_little_endian(
272 	 &( data[ 50 ] ),
273 	 number_of_guid_strings );
274 
275 #if defined( HAVE_DEBUG_OUTPUT )
276 	if( libcnotify_verbose != 0 )
277 	{
278 		byte_stream_copy_to_uint32_little_endian(
279 		 &( data[ 10 ] ),
280 		 value_32bit );
281 		libcnotify_printf(
282 		 "%s: unknown2\t\t\t\t: 0x%08" PRIx32 "\n",
283 		 function,
284 		 value_32bit );
285 
286 		byte_stream_copy_to_uint16_little_endian(
287 		 &( data[ 14 ] ),
288 		 value_16bit );
289 		libcnotify_printf(
290 		 "%s: unknown3\t\t\t\t: 0x%04" PRIx16 "\n",
291 		 function,
292 		 value_16bit );
293 
294 		byte_stream_copy_to_uint16_little_endian(
295 		 &( data[ 16 ] ),
296 		 value_16bit );
297 		libcnotify_printf(
298 		 "%s: unknown4\t\t\t\t: 0x%04" PRIx16 "\n",
299 		 function,
300 		 value_16bit );
301 
302 		byte_stream_copy_to_uint16_little_endian(
303 		 &( data[ 18 ] ),
304 		 value_16bit );
305 		libcnotify_printf(
306 		 "%s: unknown5\t\t\t\t: 0x%04" PRIx16 "\n",
307 		 function,
308 		 value_16bit );
309 
310 		byte_stream_copy_to_uint16_little_endian(
311 		 &( data[ 20 ] ),
312 		 value_16bit );
313 		libcnotify_printf(
314 		 "%s: unknown6\t\t\t\t: 0x%04" PRIx16 "\n",
315 		 function,
316 		 value_16bit );
317 
318 		byte_stream_copy_to_uint32_little_endian(
319 		 &( data[ 22 ] ),
320 		 value_32bit );
321 		libcnotify_printf(
322 		 "%s: unknown7\t\t\t\t: 0x%08" PRIx32 "\n",
323 		 function,
324 		 value_32bit );
325 
326 		libcnotify_printf(
327 		 "%s: unknown8:\n",
328 		 function );
329 		libcnotify_print_data(
330 		 &( data[ 26 ] ),
331 		 8,
332 		 0 );
333 
334 		byte_stream_copy_to_uint32_little_endian(
335 		 &( data[ 34 ] ),
336 		 value_32bit );
337 		libcnotify_printf(
338 		 "%s: unknown9\t\t\t\t: 0x%08" PRIx32 "\n",
339 		 function,
340 		 value_32bit );
341 
342 		libcnotify_printf(
343 		 "%s: name string size\t\t\t: %" PRIu32 "\n",
344 		 function,
345 		 name_string_size );
346 
347 		libcnotify_printf(
348 		 "%s: identifier string size\t\t\t: %" PRIu32 "\n",
349 		 function,
350 		 identifier_string_size );
351 
352 		libcnotify_printf(
353 		 "%s: file system string size\t\t\t: %" PRIu32 "\n",
354 		 function,
355 		 file_system_string_size );
356 
357 		libcnotify_printf(
358 		 "%s: number of GUID strings\t\t\t: %" PRIu32 "\n",
359 		 function,
360 		 number_of_guid_strings );
361 	}
362 #endif
363 	data_offset = 54;
364 
365 	if( name_string_size > 0 )
366 	{
367 		name_string_size *= 2;
368 
369 /* TODO check bounds */
370 #if defined( HAVE_DEBUG_OUTPUT )
371 		if( libcnotify_verbose != 0 )
372 		{
373 			if( libfwsi_debug_print_utf16_string_value(
374 			     function,
375 			     "name\t\t\t\t\t",
376 			     &( data[ data_offset ] ),
377 			     name_string_size,
378 			     LIBUNA_ENDIAN_LITTLE,
379 			     error ) != 1 )
380 			{
381 				libcerror_error_set(
382 				 error,
383 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
384 				 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
385 				 "%s: unable to print UTF-16 string value.",
386 				 function );
387 
388 				return( -1 );
389 			}
390 		}
391 #endif
392 		data_offset += name_string_size;
393 	}
394 	if( identifier_string_size > 0 )
395 	{
396 		identifier_string_size *= 2;
397 
398 /* TODO check bounds */
399 #if defined( HAVE_DEBUG_OUTPUT )
400 		if( libcnotify_verbose != 0 )
401 		{
402 			if( libfwsi_debug_print_utf16_string_value(
403 			     function,
404 			     "identifier\t\t\t\t",
405 			     &( data[ data_offset ] ),
406 			     identifier_string_size,
407 			     LIBUNA_ENDIAN_LITTLE,
408 			     error ) != 1 )
409 			{
410 				libcerror_error_set(
411 				 error,
412 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
413 				 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
414 				 "%s: unable to print UTF-16 string value.",
415 				 function );
416 
417 				return( -1 );
418 			}
419 		}
420 #endif
421 		data_offset += identifier_string_size;
422 	}
423 	if( file_system_string_size > 0 )
424 	{
425 		file_system_string_size *= 2;
426 
427 /* TODO check bounds */
428 #if defined( HAVE_DEBUG_OUTPUT )
429 		if( libcnotify_verbose != 0 )
430 		{
431 			if( libfwsi_debug_print_utf16_string_value(
432 			     function,
433 			     "file system\t\t\t\t",
434 			     &( data[ data_offset ] ),
435 			     file_system_string_size,
436 			     LIBUNA_ENDIAN_LITTLE,
437 			     error ) != 1 )
438 			{
439 				libcerror_error_set(
440 				 error,
441 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
442 				 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
443 				 "%s: unable to print UTF-16 string value.",
444 				 function );
445 
446 				return( -1 );
447 			}
448 		}
449 #endif
450 		data_offset += file_system_string_size;
451 	}
452 	for( guid_string_index = 0;
453 	     guid_string_index < number_of_guid_strings;
454 	     guid_string_index++ )
455 	{
456 /* TODO check bounds */
457 #if defined( HAVE_DEBUG_OUTPUT )
458 		if( libcnotify_verbose != 0 )
459 		{
460 			if( libfwsi_debug_print_utf16_string_value(
461 			     function,
462 			     "GUID\t\t\t\t\t",
463 			     &( data[ data_offset ] ),
464 			     78,
465 			     LIBUNA_ENDIAN_LITTLE,
466 			     error ) != 1 )
467 			{
468 				libcerror_error_set(
469 				 error,
470 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
471 				 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
472 				 "%s: unable to print UTF-16 string value.",
473 				 function );
474 
475 				return( -1 );
476 			}
477 		}
478 #endif
479 		data_offset += 78;
480 	}
481 /* TODO move to common MTP property values function */
482 	if( data_offset < ( data_size - 4 ) )
483 	{
484 #if defined( HAVE_DEBUG_OUTPUT )
485 		if( libcnotify_verbose != 0 )
486 		{
487 			byte_stream_copy_to_uint32_little_endian(
488 			 &( data[ data_offset ] ),
489 			 value_32bit );
490 			libcnotify_printf(
491 			 "%s: unknown10\t\t\t\t: 0x%08" PRIx32 "\n",
492 			 function,
493 			 value_32bit );
494 		}
495 #endif
496 		data_offset += 4;
497 	}
498 	if( data_offset < ( data_size - 16 ) )
499 	{
500 #if defined( HAVE_DEBUG_OUTPUT )
501 		if( libcnotify_verbose != 0 )
502 		{
503 			if( libfwsi_debug_print_guid_value(
504 			     function,
505 			     "class identifier\t\t\t",
506 			     &( data[ data_offset ] ),
507 			     16,
508 			     LIBFGUID_ENDIAN_LITTLE,
509 			     LIBFGUID_STRING_FORMAT_FLAG_USE_UPPER_CASE | LIBFGUID_STRING_FORMAT_FLAG_USE_SURROUNDING_BRACES,
510 			     error ) != 1 )
511 			{
512 				libcerror_error_set(
513 				 error,
514 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
515 				 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
516 				 "%s: unable to print GUID value.",
517 				 function );
518 
519 				return( -1 );
520 			}
521 		}
522 #endif
523 		data_offset += 16;
524 	}
525 	if( data_offset < ( data_size - 4 ) )
526 	{
527 		byte_stream_copy_to_uint32_little_endian(
528 		 &( data[ data_offset ] ),
529 		 number_of_properties );
530 
531 #if defined( HAVE_DEBUG_OUTPUT )
532 		if( libcnotify_verbose != 0 )
533 		{
534 			libcnotify_printf(
535 			 "%s: number of properties\t\t\t: %" PRIu32 "\n",
536 			 function,
537 			 number_of_properties );
538 		}
539 #endif
540 		data_offset += 4;
541 	}
542 #if defined( HAVE_DEBUG_OUTPUT )
543 	if( libcnotify_verbose != 0 )
544 	{
545 		libcnotify_printf(
546 		 "\n" );
547 	}
548 #endif
549 	for( property_index = 0;
550 	     property_index < number_of_properties;
551 	     property_index++ )
552 	{
553 #if defined( HAVE_DEBUG_OUTPUT )
554 		if( libcnotify_verbose != 0 )
555 		{
556 			libcnotify_printf(
557 			 "%s: property value: %" PRIu32 "\n",
558 			 function,
559 			 property_index );
560 		}
561 #endif
562 /* TODO at least 24 bytes in size ? */
563 		if( data_offset < ( data_size - 16 ) )
564 		{
565 #if defined( HAVE_DEBUG_OUTPUT )
566 			if( libcnotify_verbose != 0 )
567 			{
568 				if( libfwsi_debug_print_guid_value(
569 				     function,
570 				     "property set identifier\t\t\t",
571 				     &( data[ data_offset ] ),
572 				     16,
573 				     LIBFGUID_ENDIAN_LITTLE,
574 				     LIBFGUID_STRING_FORMAT_FLAG_USE_UPPER_CASE | LIBFGUID_STRING_FORMAT_FLAG_USE_SURROUNDING_BRACES,
575 				     error ) != 1 )
576 				{
577 					libcerror_error_set(
578 					 error,
579 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
580 					 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
581 					 "%s: unable to print GUID value.",
582 					 function );
583 
584 					return( -1 );
585 				}
586 			}
587 #endif
588 			data_offset += 16;
589 		}
590 		if( data_offset < ( data_size - 4 ) )
591 		{
592 #if defined( HAVE_DEBUG_OUTPUT )
593 			if( libcnotify_verbose != 0 )
594 			{
595 				byte_stream_copy_to_uint32_little_endian(
596 				 &( data[ data_offset ] ),
597 				 value_32bit );
598 				libcnotify_printf(
599 				 "%s: property value identifier\t\t: %" PRIu32 "\n",
600 				 function,
601 				 value_32bit );
602 			}
603 #endif
604 			data_offset += 4;
605 		}
606 		if( data_offset < ( data_size - 4 ) )
607 		{
608 			byte_stream_copy_to_uint32_little_endian(
609 			 &( data[ data_offset ] ),
610 			 property_value_type );
611 
612 #if defined( HAVE_DEBUG_OUTPUT )
613 			if( libcnotify_verbose != 0 )
614 			{
615 				libcnotify_printf(
616 				 "%s: property value type\t\t\t: 0x%08" PRIx32 " (%s : %s)\n",
617 				 function,
618 				 property_value_type,
619 				 libfole_value_type_get_identifier(
620 				  property_value_type ),
621 				 libfole_value_type_get_description(
622 				  property_value_type ) );
623 			}
624 #endif
625 			data_offset += 4;
626 		}
627 /* TODO merge with FOLE */
628 		switch( property_value_type )
629 		{
630 			case 0x00000005UL:
631 			case 0x00000007UL:
632 			case 0x00000015UL:
633 #if defined( HAVE_DEBUG_OUTPUT )
634 				if( libcnotify_verbose != 0 )
635 				{
636 					libcnotify_printf(
637 					 "%s: value data:\n",
638 					 function );
639 					libcnotify_print_data(
640 					 &( data[ data_offset ] ),
641 					 8,
642 					 0 );
643 				}
644 #endif
645 				data_offset += 8;
646 
647 				break;
648 
649 			case 0x0000000bUL:
650 			case 0x00000012UL:
651 				if( data_offset < ( data_size - 2 ) )
652 				{
653 #if defined( HAVE_DEBUG_OUTPUT )
654 					if( libcnotify_verbose != 0 )
655 					{
656 						byte_stream_copy_to_uint16_little_endian(
657 						 &( data[ data_offset ] ),
658 						 value_16bit );
659 						libcnotify_printf(
660 						 "%s: value\t\t\t\t\t: 0x%04" PRIx16 "\n",
661 						 function,
662 						 value_16bit );
663 
664 						libcnotify_printf(
665 						 "\n" );
666 					}
667 #endif
668 					data_offset += 2;
669 				}
670 				break;
671 
672 			case 0x0000000aUL:
673 			case 0x00000013UL:
674 				if( data_offset < ( data_size - 4 ) )
675 				{
676 #if defined( HAVE_DEBUG_OUTPUT )
677 					if( libcnotify_verbose != 0 )
678 					{
679 						byte_stream_copy_to_uint32_little_endian(
680 						 &( data[ data_offset ] ),
681 						 value_32bit );
682 						libcnotify_printf(
683 						 "%s: value\t\t\t\t\t: 0x%08" PRIx32 "\n",
684 						 function,
685 						 value_32bit );
686 
687 						libcnotify_printf(
688 						 "\n" );
689 					}
690 #endif
691 					data_offset += 4;
692 				}
693 				break;
694 
695 			case 0x0000001fUL:
696 				if( data_offset < ( data_size - 4 ) )
697 				{
698 					byte_stream_copy_to_uint32_little_endian(
699 					 &( data[ data_offset ] ),
700 					 string_size );
701 
702 #if defined( HAVE_DEBUG_OUTPUT )
703 					if( libcnotify_verbose != 0 )
704 					{
705 						libcnotify_printf(
706 						 "%s: string size\t\t\t\t: %" PRIu32 "\n",
707 						 function,
708 						 string_size );
709 					}
710 #endif
711 					data_offset += 4;
712 
713 					if( string_size > 0 )
714 					{
715 #if defined( HAVE_DEBUG_OUTPUT )
716 						if( libcnotify_verbose != 0 )
717 						{
718 							if( libfwsi_debug_print_utf16_string_value(
719 							     function,
720 							     "string\t\t\t\t\t",
721 							     &( data[ data_offset ] ),
722 							     string_size,
723 							     LIBUNA_ENDIAN_LITTLE,
724 							     error ) != 1 )
725 							{
726 								libcerror_error_set(
727 								 error,
728 								 LIBCERROR_ERROR_DOMAIN_RUNTIME,
729 								 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
730 								 "%s: unable to print UTF-16 string value.",
731 								 function );
732 
733 								return( -1 );
734 							}
735 							libcnotify_printf(
736 							 "\n" );
737 						}
738 #endif
739 						data_offset += string_size;
740 					}
741 				}
742 				break;
743 
744 			case 0x00000048UL:
745 				if( data_offset < ( data_size - 16 ) )
746 				{
747 #if defined( HAVE_DEBUG_OUTPUT )
748 					if( libcnotify_verbose != 0 )
749 					{
750 						if( libfwsi_debug_print_guid_value(
751 						     function,
752 						     "GUID\t\t\t\t\t",
753 						     &( data[ data_offset ] ),
754 						     16,
755 						     LIBFGUID_ENDIAN_LITTLE,
756 						     LIBFGUID_STRING_FORMAT_FLAG_USE_UPPER_CASE | LIBFGUID_STRING_FORMAT_FLAG_USE_SURROUNDING_BRACES,
757 						     error ) != 1 )
758 						{
759 							libcerror_error_set(
760 							 error,
761 							 LIBCERROR_ERROR_DOMAIN_RUNTIME,
762 							 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
763 							 "%s: unable to print GUID value.",
764 							 function );
765 
766 							return( -1 );
767 						}
768 						libcnotify_printf(
769 						 "\n" );
770 					}
771 #endif
772 					data_offset += 16;
773 				}
774 				break;
775 		}
776 	}
777 /* TODO */
778 
779 #if defined( HAVE_DEBUG_OUTPUT )
780 	if( libcnotify_verbose != 0 )
781 	{
782 		libcnotify_printf(
783 		 "\n" );
784 	}
785 #endif
786 	return( 1 );
787 }
788 
789