1 /*
2  * Python object wrapper of libolecf_property_value_t
3  *
4  * Copyright (C) 2008-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 <types.h>
24 
25 #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI )
26 #include <stdlib.h>
27 #endif
28 
29 #include "pyolecf_datetime.h"
30 #include "pyolecf_error.h"
31 #include "pyolecf_integer.h"
32 #include "pyolecf_libcerror.h"
33 #include "pyolecf_libolecf.h"
34 #include "pyolecf_property_value.h"
35 #include "pyolecf_python.h"
36 #include "pyolecf_unused.h"
37 
38 PyMethodDef pyolecf_property_value_object_methods[] = {
39 
40 	{ "get_identifier",
41 	  (PyCFunction) pyolecf_property_value_get_identifier,
42 	  METH_NOARGS,
43 	  "get_identifier() -> Integer or None\n"
44 	  "\n"
45 	  "Retrieves the identifier." },
46 
47 	{ "get_value_type",
48 	  (PyCFunction) pyolecf_property_value_get_value_type,
49 	  METH_NOARGS,
50 	  "get_value_type() -> Integer or None\n"
51 	  "\n"
52 	  "Retrieves the value type." },
53 
54 	/* Deprecated alias of value_type */
55 
56 	{ "get_type",
57 	  (PyCFunction) pyolecf_property_value_get_value_type,
58 	  METH_NOARGS,
59 	  "get_type() -> Integer or None\n"
60 	  "\n"
61 	  "Retrieves the value type." },
62 
63 	{ "get_data",
64 	  (PyCFunction) pyolecf_property_value_get_data,
65 	  METH_NOARGS,
66 	  "get_data() -> Binary string or None\n"
67 	  "\n"
68 	  "Retrieves the data." },
69 
70 	{ "get_data_as_boolean",
71 	  (PyCFunction) pyolecf_property_value_get_data_as_boolean,
72 	  METH_NOARGS,
73 	  "get_data_as_boolean() -> Integer or None\n"
74 	  "\n"
75 	  "Retrieves the data as a boolean." },
76 
77 	{ "get_data_as_integer",
78 	  (PyCFunction) pyolecf_property_value_get_data_as_integer,
79 	  METH_NOARGS,
80 	  "get_data_as_integer() -> Integer or None\n"
81 	  "\n"
82 	  "Retrieves the data as an integer." },
83 
84 	{ "get_data_as_datetime",
85 	  (PyCFunction) pyolecf_property_value_get_data_as_datetime,
86 	  METH_NOARGS,
87 	  "get_data_as_datetime() -> Datetime or None\n"
88 	  "\n"
89 	  "Retrieves the data as a datetime object." },
90 
91 	{ "get_data_as_string",
92 	  (PyCFunction) pyolecf_property_value_get_data_as_string,
93 	  METH_NOARGS,
94 	  "get_data_as_string() -> Unicode string or None\n"
95 	  "\n"
96 	  "Retrieves the data as a string." },
97 
98 	/* Sentinel */
99 	{ NULL, NULL, 0, NULL }
100 };
101 
102 PyGetSetDef pyolecf_property_value_object_get_set_definitions[] = {
103 
104 	{ "identifier",
105 	  (getter) pyolecf_property_value_get_identifier,
106 	  (setter) 0,
107 	  "The identifier.",
108 	  NULL },
109 
110 	{ "value_type",
111 	  (getter) pyolecf_property_value_get_value_type,
112 	  (setter) 0,
113 	  "The value type.",
114 	  NULL },
115 
116 	/* Deprecated alias of value_type */
117 
118 	{ "type",
119 	  (getter) pyolecf_property_value_get_value_type,
120 	  (setter) 0,
121 	  "The value type.",
122 	  NULL },
123 
124 	{ "data",
125 	  (getter) pyolecf_property_value_get_data,
126 	  (setter) 0,
127 	  "The data.",
128 	  NULL },
129 
130 	{ "data_as_boolean",
131 	  (getter) pyolecf_property_value_get_data_as_boolean,
132 	  (setter) 0,
133 	  "The data as a boolean.",
134 	  NULL },
135 
136 	{ "data_as_integer",
137 	  (getter) pyolecf_property_value_get_data_as_integer,
138 	  (setter) 0,
139 	  "The data as an integer.",
140 	  NULL },
141 
142 	{ "data_as_datetime",
143 	  (getter) pyolecf_property_value_get_data_as_datetime,
144 	  (setter) 0,
145 	  "The data as a datetime object.",
146 	  NULL },
147 
148 	{ "data_as_string",
149 	  (getter) pyolecf_property_value_get_data_as_string,
150 	  (setter) 0,
151 	  "The data as a string.",
152 	  NULL },
153 
154 	/* Sentinel */
155 	{ NULL, NULL, NULL, NULL, NULL }
156 };
157 
158 PyTypeObject pyolecf_property_value_type_object = {
159 	PyVarObject_HEAD_INIT( NULL, 0 )
160 
161 	/* tp_name */
162 	"pyolecf.property_value",
163 	/* tp_basicsize */
164 	sizeof( pyolecf_property_value_t ),
165 	/* tp_itemsize */
166 	0,
167 	/* tp_dealloc */
168 	(destructor) pyolecf_property_value_free,
169 	/* tp_print */
170 	0,
171 	/* tp_getattr */
172 	0,
173 	/* tp_setattr */
174 	0,
175 	/* tp_compare */
176 	0,
177 	/* tp_repr */
178 	0,
179 	/* tp_as_number */
180 	0,
181 	/* tp_as_sequence */
182 	0,
183 	/* tp_as_mapping */
184 	0,
185 	/* tp_hash */
186 	0,
187 	/* tp_call */
188 	0,
189 	/* tp_str */
190 	0,
191 	/* tp_getattro */
192 	0,
193 	/* tp_setattro */
194 	0,
195 	/* tp_as_buffer */
196 	0,
197 	/* tp_flags */
198 	Py_TPFLAGS_DEFAULT,
199 	/* tp_doc */
200 	"pyolecf property value object (wraps libolecf_property_value_t)",
201 	/* tp_traverse */
202 	0,
203 	/* tp_clear */
204 	0,
205 	/* tp_richcompare */
206 	0,
207 	/* tp_weaklistoffset */
208 	0,
209 	/* tp_iter */
210 	0,
211 	/* tp_iternext */
212 	0,
213 	/* tp_methods */
214 	pyolecf_property_value_object_methods,
215 	/* tp_members */
216 	0,
217 	/* tp_getset */
218 	pyolecf_property_value_object_get_set_definitions,
219 	/* tp_base */
220 	0,
221 	/* tp_dict */
222 	0,
223 	/* tp_descr_get */
224 	0,
225 	/* tp_descr_set */
226 	0,
227 	/* tp_dictoffset */
228 	0,
229 	/* tp_init */
230 	(initproc) pyolecf_property_value_init,
231 	/* tp_alloc */
232 	0,
233 	/* tp_new */
234 	0,
235 	/* tp_free */
236 	0,
237 	/* tp_is_gc */
238 	0,
239 	/* tp_bases */
240 	NULL,
241 	/* tp_mro */
242 	NULL,
243 	/* tp_cache */
244 	NULL,
245 	/* tp_subclasses */
246 	NULL,
247 	/* tp_weaklist */
248 	NULL,
249 	/* tp_del */
250 	0
251 };
252 
253 /* Creates a new property value object
254  * Returns a Python object if successful or NULL on error
255  */
pyolecf_property_value_new(libolecf_property_value_t * property_value,PyObject * parent_object)256 PyObject *pyolecf_property_value_new(
257            libolecf_property_value_t *property_value,
258            PyObject *parent_object )
259 {
260 	pyolecf_property_value_t *pyolecf_property_value = NULL;
261 	static char *function                            = "pyolecf_property_value_new";
262 
263 	if( property_value == NULL )
264 	{
265 		PyErr_Format(
266 		 PyExc_ValueError,
267 		 "%s: invalid property value.",
268 		 function );
269 
270 		return( NULL );
271 	}
272 	/* PyObject_New does not invoke tp_init
273 	 */
274 	pyolecf_property_value = PyObject_New(
275 	                          struct pyolecf_property_value,
276 	                          &pyolecf_property_value_type_object );
277 
278 	if( pyolecf_property_value == NULL )
279 	{
280 		PyErr_Format(
281 		 PyExc_MemoryError,
282 		 "%s: unable to initialize property value.",
283 		 function );
284 
285 		goto on_error;
286 	}
287 	pyolecf_property_value->property_value = property_value;
288 	pyolecf_property_value->parent_object  = parent_object;
289 
290 	if( pyolecf_property_value->parent_object != NULL )
291 	{
292 		Py_IncRef(
293 		 pyolecf_property_value->parent_object );
294 	}
295 	return( (PyObject *) pyolecf_property_value );
296 
297 on_error:
298 	if( pyolecf_property_value != NULL )
299 	{
300 		Py_DecRef(
301 		 (PyObject *) pyolecf_property_value );
302 	}
303 	return( NULL );
304 }
305 
306 /* Initializes a property value object
307  * Returns 0 if successful or -1 on error
308  */
pyolecf_property_value_init(pyolecf_property_value_t * pyolecf_property_value)309 int pyolecf_property_value_init(
310      pyolecf_property_value_t *pyolecf_property_value )
311 {
312 	static char *function = "pyolecf_property_value_init";
313 
314 	if( pyolecf_property_value == NULL )
315 	{
316 		PyErr_Format(
317 		 PyExc_ValueError,
318 		 "%s: invalid property value.",
319 		 function );
320 
321 		return( -1 );
322 	}
323 	/* Make sure libolecf property value is set to NULL
324 	 */
325 	pyolecf_property_value->property_value = NULL;
326 
327 	PyErr_Format(
328 	 PyExc_NotImplementedError,
329 	 "%s: initialize of property value not supported.",
330 	 function );
331 
332 	return( -1 );
333 }
334 
335 /* Frees a property value object
336  */
pyolecf_property_value_free(pyolecf_property_value_t * pyolecf_property_value)337 void pyolecf_property_value_free(
338       pyolecf_property_value_t *pyolecf_property_value )
339 {
340 	struct _typeobject *ob_type = NULL;
341 	libcerror_error_t *error    = NULL;
342 	static char *function       = "pyolecf_property_value_free";
343 	int result                  = 0;
344 
345 	if( pyolecf_property_value == NULL )
346 	{
347 		PyErr_Format(
348 		 PyExc_ValueError,
349 		 "%s: invalid property value.",
350 		 function );
351 
352 		return;
353 	}
354 	ob_type = Py_TYPE(
355 	           pyolecf_property_value );
356 
357 	if( ob_type == NULL )
358 	{
359 		PyErr_Format(
360 		 PyExc_ValueError,
361 		 "%s: missing ob_type.",
362 		 function );
363 
364 		return;
365 	}
366 	if( ob_type->tp_free == NULL )
367 	{
368 		PyErr_Format(
369 		 PyExc_ValueError,
370 		 "%s: invalid ob_type - missing tp_free.",
371 		 function );
372 
373 		return;
374 	}
375 	if( pyolecf_property_value->property_value != NULL )
376 	{
377 		Py_BEGIN_ALLOW_THREADS
378 
379 		result = libolecf_property_value_free(
380 		          &( pyolecf_property_value->property_value ),
381 		          &error );
382 
383 		Py_END_ALLOW_THREADS
384 
385 		if( result != 1 )
386 		{
387 			pyolecf_error_raise(
388 			 error,
389 			 PyExc_MemoryError,
390 			 "%s: unable to free libolecf property value.",
391 			 function );
392 
393 			libcerror_error_free(
394 			 &error );
395 		}
396 	}
397 	if( pyolecf_property_value->parent_object != NULL )
398 	{
399 		Py_DecRef(
400 		 pyolecf_property_value->parent_object );
401 	}
402 	ob_type->tp_free(
403 	 (PyObject*) pyolecf_property_value );
404 }
405 
406 /* Retrieves the identifier
407  * Returns a Python object if successful or NULL on error
408  */
pyolecf_property_value_get_identifier(pyolecf_property_value_t * pyolecf_property_value,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)409 PyObject *pyolecf_property_value_get_identifier(
410            pyolecf_property_value_t *pyolecf_property_value,
411            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
412 {
413 	PyObject *integer_object = NULL;
414 	libcerror_error_t *error = NULL;
415 	static char *function    = "pyolecf_property_value_get_identifier";
416 	uint32_t value_32bit     = 0;
417 	int result               = 0;
418 
419 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
420 
421 	if( pyolecf_property_value == NULL )
422 	{
423 		PyErr_Format(
424 		 PyExc_ValueError,
425 		 "%s: invalid property value.",
426 		 function );
427 
428 		return( NULL );
429 	}
430 	Py_BEGIN_ALLOW_THREADS
431 
432 	result = libolecf_property_value_get_identifier(
433 	          pyolecf_property_value->property_value,
434 	          &value_32bit,
435 	          &error );
436 
437 	Py_END_ALLOW_THREADS
438 
439 	if( result == -1 )
440 	{
441 		pyolecf_error_raise(
442 		 error,
443 		 PyExc_IOError,
444 		 "%s: unable to retrieve identifier.",
445 		 function );
446 
447 		libcerror_error_free(
448 		 &error );
449 
450 		return( NULL );
451 	}
452 	else if( result == 0 )
453 	{
454 		Py_IncRef(
455 		 Py_None );
456 
457 		return( Py_None );
458 	}
459 	integer_object = PyLong_FromUnsignedLong(
460 	                  (unsigned long) value_32bit );
461 
462 	return( integer_object );
463 }
464 
465 /* Retrieves the value type
466  * Returns a Python object if successful or NULL on error
467  */
pyolecf_property_value_get_value_type(pyolecf_property_value_t * pyolecf_property_value,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)468 PyObject *pyolecf_property_value_get_value_type(
469            pyolecf_property_value_t *pyolecf_property_value,
470            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
471 {
472 	PyObject *integer_object = NULL;
473 	libcerror_error_t *error = NULL;
474 	static char *function    = "pyolecf_property_value_get_value_type";
475 	uint32_t value_32bit     = 0;
476 	int result               = 0;
477 
478 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
479 
480 	if( pyolecf_property_value == NULL )
481 	{
482 		PyErr_Format(
483 		 PyExc_ValueError,
484 		 "%s: invalid property value.",
485 		 function );
486 
487 		return( NULL );
488 	}
489 	Py_BEGIN_ALLOW_THREADS
490 
491 	result = libolecf_property_value_get_value_type(
492 	          pyolecf_property_value->property_value,
493 	          &value_32bit,
494 	          &error );
495 
496 	Py_END_ALLOW_THREADS
497 
498 	if( result == -1 )
499 	{
500 		pyolecf_error_raise(
501 		 error,
502 		 PyExc_IOError,
503 		 "%s: unable to retrieve value type.",
504 		 function );
505 
506 		libcerror_error_free(
507 		 &error );
508 
509 		return( NULL );
510 	}
511 	else if( result == 0 )
512 	{
513 		Py_IncRef(
514 		 Py_None );
515 
516 		return( Py_None );
517 	}
518 	integer_object = PyLong_FromUnsignedLong(
519 	                  (unsigned long) value_32bit );
520 
521 	return( integer_object );
522 }
523 
524 /* Retrieves the data
525  * Returns a Python object if successful or NULL on error
526  */
pyolecf_property_value_get_data(pyolecf_property_value_t * pyolecf_property_value,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)527 PyObject *pyolecf_property_value_get_data(
528            pyolecf_property_value_t *pyolecf_property_value,
529            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
530 {
531 	PyObject *bytes_object   = NULL;
532 	libcerror_error_t *error = NULL;
533 	char *data               = NULL;
534 	static char *function    = "pyolecf_property_value_get_data";
535 	size_t data_size         = 0;
536 	int result               = 0;
537 
538 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
539 
540 	if( pyolecf_property_value == NULL )
541 	{
542 		PyErr_Format(
543 		 PyExc_ValueError,
544 		 "%s: invalid property value.",
545 		 function );
546 
547 		return( NULL );
548 	}
549 	Py_BEGIN_ALLOW_THREADS
550 
551 	result = libolecf_property_value_get_data_size(
552 	          pyolecf_property_value->property_value,
553 	          &data_size,
554 	          &error );
555 
556 	Py_END_ALLOW_THREADS
557 
558 	if( result == -1 )
559 	{
560 		pyolecf_error_raise(
561 		 error,
562 		 PyExc_IOError,
563 		 "%s: unable to retrieve data size.",
564 		 function );
565 
566 		libcerror_error_free(
567 		 &error );
568 
569 		goto on_error;
570 	}
571 	else if( ( result == 0 )
572 	      || ( data_size == 0 ) )
573 	{
574 		Py_IncRef(
575 		 Py_None );
576 
577 		return( Py_None );
578 	}
579 	data = (char *) PyMem_Malloc(
580 	                 sizeof( char ) * data_size );
581 
582 	if( data == NULL )
583 	{
584 		PyErr_Format(
585 		 PyExc_MemoryError,
586 		 "%s: unable to create data.",
587 		 function );
588 
589 		goto on_error;
590 	}
591 	Py_BEGIN_ALLOW_THREADS
592 
593 	result = libolecf_property_value_get_data(
594 	          pyolecf_property_value->property_value,
595 	          (uint8_t *) data,
596 	          data_size,
597 	          &error );
598 
599 	Py_END_ALLOW_THREADS
600 
601 	if( result != 1 )
602 	{
603 		pyolecf_error_raise(
604 		 error,
605 		 PyExc_IOError,
606 		 "%s: unable to retrieve data.",
607 		 function );
608 
609 		libcerror_error_free(
610 		 &error );
611 
612 		goto on_error;
613 	}
614 	/* This is a binary string so include the full size
615 	 */
616 #if PY_MAJOR_VERSION >= 3
617 	bytes_object = PyBytes_FromStringAndSize(
618 	                data,
619 	                (Py_ssize_t) data_size );
620 #else
621 	bytes_object = PyString_FromStringAndSize(
622 	                data,
623 	                (Py_ssize_t) data_size );
624 #endif
625 	if( bytes_object == NULL )
626 	{
627 		PyErr_Format(
628 		 PyExc_IOError,
629 		 "%s: unable to convert data into Bytes object.",
630 		 function );
631 
632 		goto on_error;
633 	}
634 	PyMem_Free(
635 	 data );
636 
637 	return( bytes_object );
638 
639 on_error:
640 	if( data != NULL )
641 	{
642 		PyMem_Free(
643 		 data );
644 	}
645 	return( NULL );
646 }
647 
648 /* Retrieves the data as a boolean value
649  * Returns a Python object if successful or NULL on error
650  */
pyolecf_property_value_get_data_as_boolean(pyolecf_property_value_t * pyolecf_property_value,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)651 PyObject *pyolecf_property_value_get_data_as_boolean(
652            pyolecf_property_value_t *pyolecf_property_value,
653            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
654 {
655 	libcerror_error_t *error = NULL;
656 	static char *function    = "pyolecf_property_value_get_data_as_boolean";
657 	uint8_t value_boolean    = 0;
658 	int result               = 0;
659 
660 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
661 
662 	if( pyolecf_property_value == NULL )
663 	{
664 		PyErr_Format(
665 		 PyExc_ValueError,
666 		 "%s: invalid property value.",
667 		 function );
668 
669 		return( NULL );
670 	}
671 	Py_BEGIN_ALLOW_THREADS
672 
673 	result = libolecf_property_value_get_data_as_boolean(
674 	          pyolecf_property_value->property_value,
675 	          &value_boolean,
676 	          &error );
677 
678 	Py_END_ALLOW_THREADS
679 
680 	if( result == -1 )
681 	{
682 		pyolecf_error_raise(
683 		 error,
684 		 PyExc_IOError,
685 		 "%s: unable to retrieve boolean value.",
686 		 function );
687 
688 		libcerror_error_free(
689 		 &error );
690 
691 		return( NULL );
692 	}
693 	if( value_boolean != 0x00 )
694 	{
695 		Py_IncRef(
696 		 Py_True );
697 
698 		return( Py_True );
699 	}
700 	Py_IncRef(
701 	 Py_False );
702 
703 	return( Py_False );
704 }
705 
706 /* Retrieves the data as an integer value
707  * Returns a Python object if successful or NULL on error
708  */
pyolecf_property_value_get_data_as_integer(pyolecf_property_value_t * pyolecf_property_value,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)709 PyObject *pyolecf_property_value_get_data_as_integer(
710            pyolecf_property_value_t *pyolecf_property_value,
711            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
712 {
713 	PyObject *integer_object = NULL;
714 	libcerror_error_t *error = NULL;
715 	static char *function    = "pyolecf_property_value_get_data_as_integer";
716 	uint64_t value_64bit     = 0;
717 	int64_t integer_value    = 0;
718 	uint32_t value_32bit     = 0;
719 	uint32_t value_type      = 0;
720 	uint16_t value_16bit     = 0;
721 	int result               = 0;
722 
723 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
724 
725 	if( pyolecf_property_value == NULL )
726 	{
727 		PyErr_Format(
728 		 PyExc_ValueError,
729 		 "%s: invalid property value.",
730 		 function );
731 
732 		return( NULL );
733 	}
734 	Py_BEGIN_ALLOW_THREADS
735 
736 	result = libolecf_property_value_get_value_type(
737 	          pyolecf_property_value->property_value,
738 	          &value_type,
739 	          &error );
740 
741 	Py_END_ALLOW_THREADS
742 
743 	if( result != 1 )
744 	{
745 		pyolecf_error_raise(
746 		 error,
747 		 PyExc_IOError,
748 		 "%s: unable to retrieve value type.",
749 		 function );
750 
751 		libcerror_error_free(
752 		 &error );
753 
754 		return( NULL );
755 	}
756 	switch( value_type )
757 	{
758 		case LIBOLECF_VALUE_TYPE_INTEGER_16BIT_SIGNED:
759 		case LIBOLECF_VALUE_TYPE_INTEGER_16BIT_UNSIGNED:
760 			Py_BEGIN_ALLOW_THREADS
761 
762 			result = libolecf_property_value_get_data_as_16bit_integer(
763 			          pyolecf_property_value->property_value,
764 			          &value_16bit,
765 			          &error );
766 
767 			Py_END_ALLOW_THREADS
768 
769 			if( value_type == LIBOLECF_VALUE_TYPE_INTEGER_16BIT_SIGNED )
770 			{
771 				/* Interpret the 16-bit value as signed
772 				 */
773 				integer_value = (int16_t) value_16bit;
774 			}
775 			else
776 			{
777 				integer_value = value_16bit;
778 			}
779 			break;
780 
781 		case LIBOLECF_VALUE_TYPE_INTEGER_32BIT_SIGNED:
782 		case LIBOLECF_VALUE_TYPE_INTEGER_32BIT_UNSIGNED:
783 			Py_BEGIN_ALLOW_THREADS
784 
785 			result = libolecf_property_value_get_data_as_32bit_integer(
786 			          pyolecf_property_value->property_value,
787 			          &value_32bit,
788 			          &error );
789 
790 			Py_END_ALLOW_THREADS
791 
792 			if( value_type == LIBOLECF_VALUE_TYPE_INTEGER_32BIT_SIGNED )
793 			{
794 				/* Interpret the 32-bit value as signed
795 				 */
796 				integer_value = (int32_t) value_32bit;
797 			}
798 			else
799 			{
800 				integer_value = value_32bit;
801 			}
802 			break;
803 
804 		case LIBOLECF_VALUE_TYPE_INTEGER_64BIT_SIGNED:
805 		case LIBOLECF_VALUE_TYPE_INTEGER_64BIT_UNSIGNED:
806 			Py_BEGIN_ALLOW_THREADS
807 
808 			result = libolecf_property_value_get_data_as_64bit_integer(
809 			          pyolecf_property_value->property_value,
810 			          &value_64bit,
811 			          &error );
812 
813 			Py_END_ALLOW_THREADS
814 
815 			if( value_type == LIBOLECF_VALUE_TYPE_INTEGER_64BIT_SIGNED )
816 			{
817 				/* Interpret the 64-bit value as signed
818 				 */
819 				integer_value = (int64_t) value_64bit;
820 			}
821 			else
822 			{
823 				integer_value = value_64bit;
824 			}
825 			break;
826 
827 		case LIBOLECF_VALUE_TYPE_FILETIME:
828 			Py_BEGIN_ALLOW_THREADS
829 
830 			result = libolecf_property_value_get_data_as_filetime(
831 			          pyolecf_property_value->property_value,
832 			          &value_64bit,
833 			          &error );
834 
835 			Py_END_ALLOW_THREADS
836 
837 			integer_value = value_64bit;
838 
839 			break;
840 
841 		default:
842 			PyErr_Format(
843 			 PyExc_IOError,
844 			 "%s: value is not an integer type.",
845 			 function );
846 
847 			return( NULL );
848 	}
849 	if( result == -1 )
850 	{
851 		pyolecf_error_raise(
852 		 error,
853 		 PyExc_IOError,
854 		 "%s: unable to retrieve integer value.",
855 		 function );
856 
857 		libcerror_error_free(
858 		 &error );
859 
860 		return( NULL );
861 	}
862 	switch( value_type )
863 	{
864 		case LIBOLECF_VALUE_TYPE_INTEGER_16BIT_SIGNED:
865 		case LIBOLECF_VALUE_TYPE_INTEGER_32BIT_SIGNED:
866 		case LIBOLECF_VALUE_TYPE_INTEGER_64BIT_SIGNED:
867 			integer_object = pyolecf_integer_signed_new_from_64bit(
868 			                  integer_value );
869 			break;
870 
871 		case LIBOLECF_VALUE_TYPE_INTEGER_16BIT_UNSIGNED:
872 		case LIBOLECF_VALUE_TYPE_INTEGER_32BIT_UNSIGNED:
873 		case LIBOLECF_VALUE_TYPE_INTEGER_64BIT_UNSIGNED:
874 		case LIBOLECF_VALUE_TYPE_FILETIME:
875 			integer_object = pyolecf_integer_unsigned_new_from_64bit(
876 			                  integer_value );
877 			break;
878 	}
879 	return( integer_object );
880 }
881 
882 /* Retrieves the data as an datetime value
883  * Returns a Python object if successful or NULL on error
884  */
pyolecf_property_value_get_data_as_datetime(pyolecf_property_value_t * pyolecf_property_value,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)885 PyObject *pyolecf_property_value_get_data_as_datetime(
886            pyolecf_property_value_t *pyolecf_property_value,
887            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
888 {
889 	PyObject *datetime_object = NULL;
890 	libcerror_error_t *error  = NULL;
891 	static char *function     = "pyolecf_property_value_get_data_as_datetime";
892 	uint64_t value_64bit      = 0;
893 	uint32_t value_type       = 0;
894 	int result                = 0;
895 
896 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
897 
898 	if( pyolecf_property_value == NULL )
899 	{
900 		PyErr_Format(
901 		 PyExc_ValueError,
902 		 "%s: invalid property value.",
903 		 function );
904 
905 		return( NULL );
906 	}
907 	Py_BEGIN_ALLOW_THREADS
908 
909 	result = libolecf_property_value_get_value_type(
910 	          pyolecf_property_value->property_value,
911 	          &value_type,
912 	          &error );
913 
914 	Py_END_ALLOW_THREADS
915 
916 	if( result != 1 )
917 	{
918 		pyolecf_error_raise(
919 		 error,
920 		 PyExc_IOError,
921 		 "%s: unable to retrieve value type.",
922 		 function );
923 
924 		libcerror_error_free(
925 		 &error );
926 
927 		return( NULL );
928 	}
929 	switch( value_type )
930 	{
931 		case LIBOLECF_VALUE_TYPE_FILETIME:
932 			Py_BEGIN_ALLOW_THREADS
933 
934 			result = libolecf_property_value_get_data_as_filetime(
935 			          pyolecf_property_value->property_value,
936 			          &value_64bit,
937 			          &error );
938 
939 			Py_END_ALLOW_THREADS
940 
941 			datetime_object = pyolecf_datetime_new_from_filetime(
942 			                   value_64bit );
943 			break;
944 
945 		default:
946 			PyErr_Format(
947 			 PyExc_IOError,
948 			 "%s: value is not an datetime type.",
949 			 function );
950 
951 			return( NULL );
952 	}
953 	if( result == -1 )
954 	{
955 		pyolecf_error_raise(
956 		 error,
957 		 PyExc_IOError,
958 		 "%s: unable to retrieve datetime value.",
959 		 function );
960 
961 		libcerror_error_free(
962 		 &error );
963 
964 		return( NULL );
965 	}
966 	return( datetime_object );
967 }
968 
969 /* Retrieves the data as a string
970  * Returns a Python object if successful or NULL on error
971  */
pyolecf_property_value_get_data_as_string(pyolecf_property_value_t * pyolecf_property_value,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)972 PyObject *pyolecf_property_value_get_data_as_string(
973            pyolecf_property_value_t *pyolecf_property_value,
974            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
975 {
976 	PyObject *string_object  = NULL;
977 	libcerror_error_t *error = NULL;
978 	const char *errors       = NULL;
979 	static char *function    = "pyolecf_value_get_data_as_string";
980 	char *utf8_string        = NULL;
981 	size_t utf8_string_size  = 0;
982 	int result               = 0;
983 
984 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
985 
986 	if( pyolecf_property_value == NULL )
987 	{
988 		PyErr_Format(
989 		 PyExc_ValueError,
990 		 "%s: invalid property value.",
991 		 function );
992 
993 		return( NULL );
994 	}
995 	Py_BEGIN_ALLOW_THREADS
996 
997 	result = libolecf_property_value_get_data_as_utf8_string_size(
998 	          pyolecf_property_value->property_value,
999 	          &utf8_string_size,
1000 	          &error );
1001 
1002 	Py_END_ALLOW_THREADS
1003 
1004 	if( result == -1 )
1005 	{
1006 		pyolecf_error_raise(
1007 		 error,
1008 		 PyExc_IOError,
1009 		 "%s: unable to determine size of data as UTF-8 string.",
1010 		 function );
1011 
1012 		libcerror_error_free(
1013 		 &error );
1014 
1015 		goto on_error;
1016 	}
1017 	else if( ( result == 0 )
1018 	      || ( utf8_string_size == 0 ) )
1019 	{
1020 		Py_IncRef(
1021 		 Py_None );
1022 
1023 		return( Py_None );
1024 	}
1025 	utf8_string = (char *) PyMem_Malloc(
1026 	                        sizeof( char ) * utf8_string_size );
1027 
1028 	if( utf8_string == NULL )
1029 	{
1030 		PyErr_Format(
1031 		 PyExc_MemoryError,
1032 		 "%s: unable to create UTF-8 string.",
1033 		 function );
1034 
1035 		goto on_error;
1036 	}
1037 	Py_BEGIN_ALLOW_THREADS
1038 
1039 	result = libolecf_property_value_get_data_as_utf8_string(
1040 	          pyolecf_property_value->property_value,
1041 	          (uint8_t *) utf8_string,
1042 	          utf8_string_size,
1043 	          &error );
1044 
1045 	Py_END_ALLOW_THREADS
1046 
1047 	if( result != 1 )
1048 	{
1049 		pyolecf_error_raise(
1050 		 error,
1051 		 PyExc_IOError,
1052 		 "%s: unable to retrieve data as UTF-8 string.",
1053 		 function );
1054 
1055 		libcerror_error_free(
1056 		 &error );
1057 
1058 		goto on_error;
1059 	}
1060 	/* Pass the string length to PyUnicode_DecodeUTF8 otherwise it makes
1061 	 * the end of string character is part of the string
1062 	 */
1063 	string_object = PyUnicode_DecodeUTF8(
1064 	                 utf8_string,
1065 	                 (Py_ssize_t) utf8_string_size - 1,
1066 	                 errors );
1067 
1068 	if( string_object == NULL )
1069 	{
1070 		PyErr_Format(
1071 		 PyExc_IOError,
1072 		 "%s: unable to convert UTF-8 string into Unicode object.",
1073 		 function );
1074 
1075 		goto on_error;
1076 	}
1077 	PyMem_Free(
1078 	 utf8_string );
1079 
1080 	return( string_object );
1081 
1082 on_error:
1083 	if( utf8_string != NULL )
1084 	{
1085 		PyMem_Free(
1086 		 utf8_string );
1087 	}
1088 	return( NULL );
1089 }
1090 
1091