1 /*
2 * Python object wrapper of libcreg_file_t
3 *
4 * Copyright (C) 2013-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 <narrow_string.h>
24 #include <types.h>
25
26 #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI )
27 #include <stdlib.h>
28 #endif
29
30 #include "pycreg_codepage.h"
31 #include "pycreg_error.h"
32 #include "pycreg_file.h"
33 #include "pycreg_file_object_io_handle.h"
34 #include "pycreg_key.h"
35 #include "pycreg_libbfio.h"
36 #include "pycreg_libcerror.h"
37 #include "pycreg_libclocale.h"
38 #include "pycreg_libcreg.h"
39 #include "pycreg_python.h"
40 #include "pycreg_unused.h"
41
42 #if !defined( LIBCREG_HAVE_BFIO )
43
44 LIBCREG_EXTERN \
45 int libcreg_file_open_file_io_handle(
46 libcreg_file_t *file,
47 libbfio_handle_t *file_io_handle,
48 int access_flags,
49 libcreg_error_t **error );
50
51 #endif /* !defined( LIBCREG_HAVE_BFIO ) */
52
53 PyMethodDef pycreg_file_object_methods[] = {
54
55 { "signal_abort",
56 (PyCFunction) pycreg_file_signal_abort,
57 METH_NOARGS,
58 "signal_abort() -> None\n"
59 "\n"
60 "Signals the file to abort the current activity." },
61
62 { "open",
63 (PyCFunction) pycreg_file_open,
64 METH_VARARGS | METH_KEYWORDS,
65 "open(filename, mode='r') -> None\n"
66 "\n"
67 "Opens a file." },
68
69 { "open_file_object",
70 (PyCFunction) pycreg_file_open_file_object,
71 METH_VARARGS | METH_KEYWORDS,
72 "open_file_object(file_object, mode='r') -> None\n"
73 "\n"
74 "Opens a file using a file-like object." },
75
76 { "close",
77 (PyCFunction) pycreg_file_close,
78 METH_NOARGS,
79 "close() -> None\n"
80 "\n"
81 "Closes a file." },
82
83 { "is_corrupted",
84 (PyCFunction) pycreg_file_is_corrupted,
85 METH_NOARGS,
86 "is_corrupted() -> Boolean\n"
87 "\n"
88 "Determines if the file is corrupted." },
89
90 { "get_ascii_codepage",
91 (PyCFunction) pycreg_file_get_ascii_codepage,
92 METH_NOARGS,
93 "get_ascii_codepage() -> String\n"
94 "\n"
95 "Retrieves the codepage for ASCII strings used in the file." },
96
97 { "set_ascii_codepage",
98 (PyCFunction) pycreg_file_set_ascii_codepage,
99 METH_VARARGS | METH_KEYWORDS,
100 "set_ascii_codepage(codepage) -> None\n"
101 "\n"
102 "Sets the codepage for ASCII strings used in the file.\n"
103 "Expects the codepage to be a string containing a Python codec definition." },
104
105 { "get_format_version",
106 (PyCFunction) pycreg_file_get_format_version,
107 METH_NOARGS,
108 "get_format_version() -> Unicode string\n"
109 "\n"
110 "Retrieves the format version." },
111
112 { "get_type",
113 (PyCFunction) pycreg_file_get_type,
114 METH_NOARGS,
115 "get_type() -> Integer\n"
116 "\n"
117 "Retrieves the type." },
118
119 { "get_root_key",
120 (PyCFunction) pycreg_file_get_root_key,
121 METH_NOARGS,
122 "get_root_key() -> Object\n"
123 "\n"
124 "Retrieves the root key." },
125
126 { "get_key_by_path",
127 (PyCFunction) pycreg_file_get_key_by_path,
128 METH_VARARGS | METH_KEYWORDS,
129 "get_key_by_path(path) -> Object or None\n"
130 "\n"
131 "Retrieves the key specified by the path." },
132
133 /* Sentinel */
134 { NULL, NULL, 0, NULL }
135 };
136
137 PyGetSetDef pycreg_file_object_get_set_definitions[] = {
138
139 { "corrupted",
140 (getter) pycreg_file_is_corrupted,
141 (setter) 0,
142 "Value to indicate the file is corrupted.",
143 NULL },
144
145 { "ascii_codepage",
146 (getter) pycreg_file_get_ascii_codepage,
147 (setter) pycreg_file_set_ascii_codepage_setter,
148 "The codepage used for ASCII strings in the file.",
149 NULL },
150
151 { "format_version",
152 (getter) pycreg_file_get_format_version,
153 (setter) 0,
154 "The format version.",
155 NULL },
156
157 { "type",
158 (getter) pycreg_file_get_type,
159 (setter) 0,
160 "The type.",
161 NULL },
162
163 { "root_key",
164 (getter) pycreg_file_get_root_key,
165 (setter) 0,
166 "The root key.",
167 NULL },
168
169 /* Sentinel */
170 { NULL, NULL, NULL, NULL, NULL }
171 };
172
173 PyTypeObject pycreg_file_type_object = {
174 PyVarObject_HEAD_INIT( NULL, 0 )
175
176 /* tp_name */
177 "pycreg.file",
178 /* tp_basicsize */
179 sizeof( pycreg_file_t ),
180 /* tp_itemsize */
181 0,
182 /* tp_dealloc */
183 (destructor) pycreg_file_free,
184 /* tp_print */
185 0,
186 /* tp_getattr */
187 0,
188 /* tp_setattr */
189 0,
190 /* tp_compare */
191 0,
192 /* tp_repr */
193 0,
194 /* tp_as_number */
195 0,
196 /* tp_as_sequence */
197 0,
198 /* tp_as_mapping */
199 0,
200 /* tp_hash */
201 0,
202 /* tp_call */
203 0,
204 /* tp_str */
205 0,
206 /* tp_getattro */
207 0,
208 /* tp_setattro */
209 0,
210 /* tp_as_buffer */
211 0,
212 /* tp_flags */
213 Py_TPFLAGS_DEFAULT,
214 /* tp_doc */
215 "pycreg file object (wraps libcreg_file_t)",
216 /* tp_traverse */
217 0,
218 /* tp_clear */
219 0,
220 /* tp_richcompare */
221 0,
222 /* tp_weaklistoffset */
223 0,
224 /* tp_iter */
225 0,
226 /* tp_iternext */
227 0,
228 /* tp_methods */
229 pycreg_file_object_methods,
230 /* tp_members */
231 0,
232 /* tp_getset */
233 pycreg_file_object_get_set_definitions,
234 /* tp_base */
235 0,
236 /* tp_dict */
237 0,
238 /* tp_descr_get */
239 0,
240 /* tp_descr_set */
241 0,
242 /* tp_dictoffset */
243 0,
244 /* tp_init */
245 (initproc) pycreg_file_init,
246 /* tp_alloc */
247 0,
248 /* tp_new */
249 0,
250 /* tp_free */
251 0,
252 /* tp_is_gc */
253 0,
254 /* tp_bases */
255 NULL,
256 /* tp_mro */
257 NULL,
258 /* tp_cache */
259 NULL,
260 /* tp_subclasses */
261 NULL,
262 /* tp_weaklist */
263 NULL,
264 /* tp_del */
265 0
266 };
267
268 /* Initializes a file object
269 * Returns 0 if successful or -1 on error
270 */
pycreg_file_init(pycreg_file_t * pycreg_file)271 int pycreg_file_init(
272 pycreg_file_t *pycreg_file )
273 {
274 libcerror_error_t *error = NULL;
275 static char *function = "pycreg_file_init";
276
277 if( pycreg_file == NULL )
278 {
279 PyErr_Format(
280 PyExc_ValueError,
281 "%s: invalid file.",
282 function );
283
284 return( -1 );
285 }
286 /* Make sure libcreg file is set to NULL
287 */
288 pycreg_file->file = NULL;
289 pycreg_file->file_io_handle = NULL;
290
291 if( libcreg_file_initialize(
292 &( pycreg_file->file ),
293 &error ) != 1 )
294 {
295 pycreg_error_raise(
296 error,
297 PyExc_MemoryError,
298 "%s: unable to initialize file.",
299 function );
300
301 libcerror_error_free(
302 &error );
303
304 return( -1 );
305 }
306 return( 0 );
307 }
308
309 /* Frees a file object
310 */
pycreg_file_free(pycreg_file_t * pycreg_file)311 void pycreg_file_free(
312 pycreg_file_t *pycreg_file )
313 {
314 struct _typeobject *ob_type = NULL;
315 libcerror_error_t *error = NULL;
316 static char *function = "pycreg_file_free";
317 int result = 0;
318
319 if( pycreg_file == NULL )
320 {
321 PyErr_Format(
322 PyExc_ValueError,
323 "%s: invalid file.",
324 function );
325
326 return;
327 }
328 ob_type = Py_TYPE(
329 pycreg_file );
330
331 if( ob_type == NULL )
332 {
333 PyErr_Format(
334 PyExc_ValueError,
335 "%s: missing ob_type.",
336 function );
337
338 return;
339 }
340 if( ob_type->tp_free == NULL )
341 {
342 PyErr_Format(
343 PyExc_ValueError,
344 "%s: invalid ob_type - missing tp_free.",
345 function );
346
347 return;
348 }
349 if( pycreg_file->file != NULL )
350 {
351 Py_BEGIN_ALLOW_THREADS
352
353 result = libcreg_file_free(
354 &( pycreg_file->file ),
355 &error );
356
357 Py_END_ALLOW_THREADS
358
359 if( result != 1 )
360 {
361 pycreg_error_raise(
362 error,
363 PyExc_MemoryError,
364 "%s: unable to free libcreg file.",
365 function );
366
367 libcerror_error_free(
368 &error );
369 }
370 }
371 ob_type->tp_free(
372 (PyObject*) pycreg_file );
373 }
374
375 /* Signals the file to abort the current activity
376 * Returns a Python object if successful or NULL on error
377 */
pycreg_file_signal_abort(pycreg_file_t * pycreg_file,PyObject * arguments PYCREG_ATTRIBUTE_UNUSED)378 PyObject *pycreg_file_signal_abort(
379 pycreg_file_t *pycreg_file,
380 PyObject *arguments PYCREG_ATTRIBUTE_UNUSED )
381 {
382 libcerror_error_t *error = NULL;
383 static char *function = "pycreg_file_signal_abort";
384 int result = 0;
385
386 PYCREG_UNREFERENCED_PARAMETER( arguments )
387
388 if( pycreg_file == NULL )
389 {
390 PyErr_Format(
391 PyExc_ValueError,
392 "%s: invalid file.",
393 function );
394
395 return( NULL );
396 }
397 Py_BEGIN_ALLOW_THREADS
398
399 result = libcreg_file_signal_abort(
400 pycreg_file->file,
401 &error );
402
403 Py_END_ALLOW_THREADS
404
405 if( result != 1 )
406 {
407 pycreg_error_raise(
408 error,
409 PyExc_IOError,
410 "%s: unable to signal abort.",
411 function );
412
413 libcerror_error_free(
414 &error );
415
416 return( NULL );
417 }
418 Py_IncRef(
419 Py_None );
420
421 return( Py_None );
422 }
423
424 /* Opens a file
425 * Returns a Python object if successful or NULL on error
426 */
pycreg_file_open(pycreg_file_t * pycreg_file,PyObject * arguments,PyObject * keywords)427 PyObject *pycreg_file_open(
428 pycreg_file_t *pycreg_file,
429 PyObject *arguments,
430 PyObject *keywords )
431 {
432 PyObject *string_object = NULL;
433 libcerror_error_t *error = NULL;
434 const char *filename_narrow = NULL;
435 static char *function = "pycreg_file_open";
436 static char *keyword_list[] = { "filename", "mode", NULL };
437 char *mode = NULL;
438 int result = 0;
439
440 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
441 const wchar_t *filename_wide = NULL;
442 #else
443 PyObject *utf8_string_object = NULL;
444 #endif
445
446 if( pycreg_file == NULL )
447 {
448 PyErr_Format(
449 PyExc_ValueError,
450 "%s: invalid file.",
451 function );
452
453 return( NULL );
454 }
455 /* Note that PyArg_ParseTupleAndKeywords with "s" will force Unicode strings to be converted to narrow character string.
456 * On Windows the narrow character strings contains an extended ASCII string with a codepage. Hence we get a conversion
457 * exception. This will also fail if the default encoding is not set correctly. We cannot use "u" here either since that
458 * does not allow us to pass non Unicode string objects and Python (at least 2.7) does not seems to automatically upcast them.
459 */
460 if( PyArg_ParseTupleAndKeywords(
461 arguments,
462 keywords,
463 "O|s",
464 keyword_list,
465 &string_object,
466 &mode ) == 0 )
467 {
468 return( NULL );
469 }
470 if( ( mode != NULL )
471 && ( mode[ 0 ] != 'r' ) )
472 {
473 PyErr_Format(
474 PyExc_ValueError,
475 "%s: unsupported mode: %s.",
476 function,
477 mode );
478
479 return( NULL );
480 }
481 PyErr_Clear();
482
483 result = PyObject_IsInstance(
484 string_object,
485 (PyObject *) &PyUnicode_Type );
486
487 if( result == -1 )
488 {
489 pycreg_error_fetch_and_raise(
490 PyExc_RuntimeError,
491 "%s: unable to determine if string object is of type Unicode.",
492 function );
493
494 return( NULL );
495 }
496 else if( result != 0 )
497 {
498 PyErr_Clear();
499
500 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
501 filename_wide = (wchar_t *) PyUnicode_AsUnicode(
502 string_object );
503 Py_BEGIN_ALLOW_THREADS
504
505 result = libcreg_file_open_wide(
506 pycreg_file->file,
507 filename_wide,
508 LIBCREG_OPEN_READ,
509 &error );
510
511 Py_END_ALLOW_THREADS
512 #else
513 utf8_string_object = PyUnicode_AsUTF8String(
514 string_object );
515
516 if( utf8_string_object == NULL )
517 {
518 pycreg_error_fetch_and_raise(
519 PyExc_RuntimeError,
520 "%s: unable to convert Unicode string to UTF-8.",
521 function );
522
523 return( NULL );
524 }
525 #if PY_MAJOR_VERSION >= 3
526 filename_narrow = PyBytes_AsString(
527 utf8_string_object );
528 #else
529 filename_narrow = PyString_AsString(
530 utf8_string_object );
531 #endif
532 Py_BEGIN_ALLOW_THREADS
533
534 result = libcreg_file_open(
535 pycreg_file->file,
536 filename_narrow,
537 LIBCREG_OPEN_READ,
538 &error );
539
540 Py_END_ALLOW_THREADS
541
542 Py_DecRef(
543 utf8_string_object );
544 #endif
545 if( result != 1 )
546 {
547 pycreg_error_raise(
548 error,
549 PyExc_IOError,
550 "%s: unable to open file.",
551 function );
552
553 libcerror_error_free(
554 &error );
555
556 return( NULL );
557 }
558 Py_IncRef(
559 Py_None );
560
561 return( Py_None );
562 }
563 PyErr_Clear();
564
565 #if PY_MAJOR_VERSION >= 3
566 result = PyObject_IsInstance(
567 string_object,
568 (PyObject *) &PyBytes_Type );
569 #else
570 result = PyObject_IsInstance(
571 string_object,
572 (PyObject *) &PyString_Type );
573 #endif
574 if( result == -1 )
575 {
576 pycreg_error_fetch_and_raise(
577 PyExc_RuntimeError,
578 "%s: unable to determine if string object is of type string.",
579 function );
580
581 return( NULL );
582 }
583 else if( result != 0 )
584 {
585 PyErr_Clear();
586
587 #if PY_MAJOR_VERSION >= 3
588 filename_narrow = PyBytes_AsString(
589 string_object );
590 #else
591 filename_narrow = PyString_AsString(
592 string_object );
593 #endif
594 Py_BEGIN_ALLOW_THREADS
595
596 result = libcreg_file_open(
597 pycreg_file->file,
598 filename_narrow,
599 LIBCREG_OPEN_READ,
600 &error );
601
602 Py_END_ALLOW_THREADS
603
604 if( result != 1 )
605 {
606 pycreg_error_raise(
607 error,
608 PyExc_IOError,
609 "%s: unable to open file.",
610 function );
611
612 libcerror_error_free(
613 &error );
614
615 return( NULL );
616 }
617 Py_IncRef(
618 Py_None );
619
620 return( Py_None );
621 }
622 PyErr_Format(
623 PyExc_TypeError,
624 "%s: unsupported string object type.",
625 function );
626
627 return( NULL );
628 }
629
630 /* Opens a file using a file-like object
631 * Returns a Python object if successful or NULL on error
632 */
pycreg_file_open_file_object(pycreg_file_t * pycreg_file,PyObject * arguments,PyObject * keywords)633 PyObject *pycreg_file_open_file_object(
634 pycreg_file_t *pycreg_file,
635 PyObject *arguments,
636 PyObject *keywords )
637 {
638 PyObject *file_object = NULL;
639 libcerror_error_t *error = NULL;
640 static char *function = "pycreg_file_open_file_object";
641 static char *keyword_list[] = { "file_object", "mode", NULL };
642 char *mode = NULL;
643 int result = 0;
644
645 if( pycreg_file == NULL )
646 {
647 PyErr_Format(
648 PyExc_ValueError,
649 "%s: invalid file.",
650 function );
651
652 return( NULL );
653 }
654 if( PyArg_ParseTupleAndKeywords(
655 arguments,
656 keywords,
657 "O|s",
658 keyword_list,
659 &file_object,
660 &mode ) == 0 )
661 {
662 return( NULL );
663 }
664 if( ( mode != NULL )
665 && ( mode[ 0 ] != 'r' ) )
666 {
667 PyErr_Format(
668 PyExc_ValueError,
669 "%s: unsupported mode: %s.",
670 function,
671 mode );
672
673 return( NULL );
674 }
675 PyErr_Clear();
676
677 result = PyObject_HasAttrString(
678 file_object,
679 "read" );
680
681 if( result != 1 )
682 {
683 PyErr_Format(
684 PyExc_TypeError,
685 "%s: unsupported file object - missing read attribute.",
686 function );
687
688 return( NULL );
689 }
690 PyErr_Clear();
691
692 result = PyObject_HasAttrString(
693 file_object,
694 "seek" );
695
696 if( result != 1 )
697 {
698 PyErr_Format(
699 PyExc_TypeError,
700 "%s: unsupported file object - missing seek attribute.",
701 function );
702
703 return( NULL );
704 }
705 if( pycreg_file->file_io_handle != NULL )
706 {
707 pycreg_error_raise(
708 error,
709 PyExc_IOError,
710 "%s: invalid file - file IO handle already set.",
711 function );
712
713 goto on_error;
714 }
715 if( pycreg_file_object_initialize(
716 &( pycreg_file->file_io_handle ),
717 file_object,
718 &error ) != 1 )
719 {
720 pycreg_error_raise(
721 error,
722 PyExc_MemoryError,
723 "%s: unable to initialize file IO handle.",
724 function );
725
726 libcerror_error_free(
727 &error );
728
729 goto on_error;
730 }
731 Py_BEGIN_ALLOW_THREADS
732
733 result = libcreg_file_open_file_io_handle(
734 pycreg_file->file,
735 pycreg_file->file_io_handle,
736 LIBCREG_OPEN_READ,
737 &error );
738
739 Py_END_ALLOW_THREADS
740
741 if( result != 1 )
742 {
743 pycreg_error_raise(
744 error,
745 PyExc_IOError,
746 "%s: unable to open file.",
747 function );
748
749 libcerror_error_free(
750 &error );
751
752 goto on_error;
753 }
754 Py_IncRef(
755 Py_None );
756
757 return( Py_None );
758
759 on_error:
760 if( pycreg_file->file_io_handle != NULL )
761 {
762 libbfio_handle_free(
763 &( pycreg_file->file_io_handle ),
764 NULL );
765 }
766 return( NULL );
767 }
768
769 /* Closes a file
770 * Returns a Python object if successful or NULL on error
771 */
pycreg_file_close(pycreg_file_t * pycreg_file,PyObject * arguments PYCREG_ATTRIBUTE_UNUSED)772 PyObject *pycreg_file_close(
773 pycreg_file_t *pycreg_file,
774 PyObject *arguments PYCREG_ATTRIBUTE_UNUSED )
775 {
776 libcerror_error_t *error = NULL;
777 static char *function = "pycreg_file_close";
778 int result = 0;
779
780 PYCREG_UNREFERENCED_PARAMETER( arguments )
781
782 if( pycreg_file == NULL )
783 {
784 PyErr_Format(
785 PyExc_ValueError,
786 "%s: invalid file.",
787 function );
788
789 return( NULL );
790 }
791 Py_BEGIN_ALLOW_THREADS
792
793 result = libcreg_file_close(
794 pycreg_file->file,
795 &error );
796
797 Py_END_ALLOW_THREADS
798
799 if( result != 0 )
800 {
801 pycreg_error_raise(
802 error,
803 PyExc_IOError,
804 "%s: unable to close file.",
805 function );
806
807 libcerror_error_free(
808 &error );
809
810 return( NULL );
811 }
812 if( pycreg_file->file_io_handle != NULL )
813 {
814 Py_BEGIN_ALLOW_THREADS
815
816 result = libbfio_handle_free(
817 &( pycreg_file->file_io_handle ),
818 &error );
819
820 Py_END_ALLOW_THREADS
821
822 if( result != 1 )
823 {
824 pycreg_error_raise(
825 error,
826 PyExc_MemoryError,
827 "%s: unable to free libbfio file IO handle.",
828 function );
829
830 libcerror_error_free(
831 &error );
832
833 return( NULL );
834 }
835 }
836 Py_IncRef(
837 Py_None );
838
839 return( Py_None );
840 }
841
842 /* Determines if the file is corrupted
843 * Returns a Python object if successful or NULL on error
844 */
pycreg_file_is_corrupted(pycreg_file_t * pycreg_file,PyObject * arguments PYCREG_ATTRIBUTE_UNUSED)845 PyObject *pycreg_file_is_corrupted(
846 pycreg_file_t *pycreg_file,
847 PyObject *arguments PYCREG_ATTRIBUTE_UNUSED )
848 {
849 libcerror_error_t *error = NULL;
850 static char *function = "pycreg_file_is_corrupted";
851 int result = 0;
852
853 PYCREG_UNREFERENCED_PARAMETER( arguments )
854
855 if( pycreg_file == NULL )
856 {
857 PyErr_Format(
858 PyExc_ValueError,
859 "%s: invalid file.",
860 function );
861
862 return( NULL );
863 }
864 Py_BEGIN_ALLOW_THREADS
865
866 result = libcreg_file_is_corrupted(
867 pycreg_file->file,
868 &error );
869
870 Py_END_ALLOW_THREADS
871
872 if( result == -1 )
873 {
874 pycreg_error_raise(
875 error,
876 PyExc_IOError,
877 "%s: unable to determine if file is corrupted.",
878 function );
879
880 libcerror_error_free(
881 &error );
882
883 return( NULL );
884 }
885 if( result != 0 )
886 {
887 Py_IncRef(
888 (PyObject *) Py_True );
889
890 return( Py_True );
891 }
892 Py_IncRef(
893 (PyObject *) Py_False );
894
895 return( Py_False );
896 }
897
898 /* Retrieves the codepage used for ASCII strings in the file
899 * Returns a Python object if successful or NULL on error
900 */
pycreg_file_get_ascii_codepage(pycreg_file_t * pycreg_file,PyObject * arguments PYCREG_ATTRIBUTE_UNUSED)901 PyObject *pycreg_file_get_ascii_codepage(
902 pycreg_file_t *pycreg_file,
903 PyObject *arguments PYCREG_ATTRIBUTE_UNUSED )
904 {
905 PyObject *string_object = NULL;
906 libcerror_error_t *error = NULL;
907 const char *codepage_string = NULL;
908 static char *function = "pycreg_file_get_ascii_codepage";
909 int ascii_codepage = 0;
910 int result = 0;
911
912 PYCREG_UNREFERENCED_PARAMETER( arguments )
913
914 if( pycreg_file == NULL )
915 {
916 PyErr_Format(
917 PyExc_ValueError,
918 "%s: invalid file.",
919 function );
920
921 return( NULL );
922 }
923 Py_BEGIN_ALLOW_THREADS
924
925 result = libcreg_file_get_ascii_codepage(
926 pycreg_file->file,
927 &ascii_codepage,
928 &error );
929
930 Py_END_ALLOW_THREADS
931
932 if( result != 1 )
933 {
934 pycreg_error_raise(
935 error,
936 PyExc_IOError,
937 "%s: unable to retrieve ASCII codepage.",
938 function );
939
940 libcerror_error_free(
941 &error );
942
943 return( NULL );
944 }
945 codepage_string = pycreg_codepage_to_string(
946 ascii_codepage );
947
948 if( codepage_string == NULL )
949 {
950 PyErr_Format(
951 PyExc_ValueError,
952 "%s: unsupported ASCII codepage: %d.",
953 function,
954 ascii_codepage );
955
956 return( NULL );
957 }
958 #if PY_MAJOR_VERSION >= 3
959 string_object = PyBytes_FromString(
960 codepage_string );
961 #else
962 string_object = PyString_FromString(
963 codepage_string );
964 #endif
965 if( string_object == NULL )
966 {
967 PyErr_Format(
968 PyExc_IOError,
969 "%s: unable to convert codepage string into string object.",
970 function );
971
972 return( NULL );
973 }
974 return( string_object );
975 }
976
977 /* Sets the codepage used for ASCII strings in the file
978 * Returns 1 if successful or -1 on error
979 */
pycreg_file_set_ascii_codepage_from_string(pycreg_file_t * pycreg_file,const char * codepage_string)980 int pycreg_file_set_ascii_codepage_from_string(
981 pycreg_file_t *pycreg_file,
982 const char *codepage_string )
983 {
984 libcerror_error_t *error = NULL;
985 static char *function = "pycreg_file_set_ascii_codepage_from_string";
986 size_t codepage_string_length = 0;
987 uint32_t feature_flags = 0;
988 int ascii_codepage = 0;
989 int result = 0;
990
991 if( pycreg_file == NULL )
992 {
993 PyErr_Format(
994 PyExc_ValueError,
995 "%s: invalid file.",
996 function );
997
998 return( -1 );
999 }
1000 if( codepage_string == NULL )
1001 {
1002 PyErr_Format(
1003 PyExc_ValueError,
1004 "%s: invalid codepage string.",
1005 function );
1006
1007 return( -1 );
1008 }
1009 codepage_string_length = narrow_string_length(
1010 codepage_string );
1011
1012 feature_flags = LIBCLOCALE_CODEPAGE_FEATURE_FLAG_HAVE_WINDOWS;
1013
1014 if( libclocale_codepage_copy_from_string(
1015 &ascii_codepage,
1016 codepage_string,
1017 codepage_string_length,
1018 feature_flags,
1019 &error ) != 1 )
1020 {
1021 pycreg_error_raise(
1022 error,
1023 PyExc_RuntimeError,
1024 "%s: unable to determine ASCII codepage.",
1025 function );
1026
1027 libcerror_error_free(
1028 &error );
1029
1030 return( -1 );
1031 }
1032 Py_BEGIN_ALLOW_THREADS
1033
1034 result = libcreg_file_set_ascii_codepage(
1035 pycreg_file->file,
1036 ascii_codepage,
1037 &error );
1038
1039 Py_END_ALLOW_THREADS
1040
1041 if( result != 1 )
1042 {
1043 pycreg_error_raise(
1044 error,
1045 PyExc_IOError,
1046 "%s: unable to set ASCII codepage.",
1047 function );
1048
1049 libcerror_error_free(
1050 &error );
1051
1052 return( -1 );
1053 }
1054 return( 1 );
1055 }
1056
1057 /* Sets the codepage used for ASCII strings in the file
1058 * Returns a Python object if successful or NULL on error
1059 */
pycreg_file_set_ascii_codepage(pycreg_file_t * pycreg_file,PyObject * arguments,PyObject * keywords)1060 PyObject *pycreg_file_set_ascii_codepage(
1061 pycreg_file_t *pycreg_file,
1062 PyObject *arguments,
1063 PyObject *keywords )
1064 {
1065 char *codepage_string = NULL;
1066 static char *keyword_list[] = { "codepage", NULL };
1067 int result = 0;
1068
1069 if( PyArg_ParseTupleAndKeywords(
1070 arguments,
1071 keywords,
1072 "s",
1073 keyword_list,
1074 &codepage_string ) == 0 )
1075 {
1076 return( NULL );
1077 }
1078 result = pycreg_file_set_ascii_codepage_from_string(
1079 pycreg_file,
1080 codepage_string );
1081
1082 if( result != 1 )
1083 {
1084 return( NULL );
1085 }
1086 Py_IncRef(
1087 Py_None );
1088
1089 return( Py_None );
1090 }
1091
1092 /* Sets the codepage used for ASCII strings in the file
1093 * Returns a Python object if successful or NULL on error
1094 */
pycreg_file_set_ascii_codepage_setter(pycreg_file_t * pycreg_file,PyObject * string_object,void * closure PYCREG_ATTRIBUTE_UNUSED)1095 int pycreg_file_set_ascii_codepage_setter(
1096 pycreg_file_t *pycreg_file,
1097 PyObject *string_object,
1098 void *closure PYCREG_ATTRIBUTE_UNUSED )
1099 {
1100 PyObject *utf8_string_object = NULL;
1101 char *codepage_string = NULL;
1102 static char *function = "pycreg_file_set_ascii_codepage_setter";
1103 int result = 0;
1104
1105 PYCREG_UNREFERENCED_PARAMETER( closure )
1106
1107 PyErr_Clear();
1108
1109 result = PyObject_IsInstance(
1110 string_object,
1111 (PyObject *) &PyUnicode_Type );
1112
1113 if( result == -1 )
1114 {
1115 pycreg_error_fetch_and_raise(
1116 PyExc_RuntimeError,
1117 "%s: unable to determine if string object is of type Unicode.",
1118 function );
1119
1120 return( -1 );
1121 }
1122 else if( result != 0 )
1123 {
1124 /* The codepage string should only contain ASCII characters.
1125 */
1126 utf8_string_object = PyUnicode_AsUTF8String(
1127 string_object );
1128
1129 if( utf8_string_object == NULL )
1130 {
1131 pycreg_error_fetch_and_raise(
1132 PyExc_RuntimeError,
1133 "%s: unable to convert Unicode string to UTF-8.",
1134 function );
1135
1136 return( -1 );
1137 }
1138 #if PY_MAJOR_VERSION >= 3
1139 codepage_string = PyBytes_AsString(
1140 utf8_string_object );
1141 #else
1142 codepage_string = PyString_AsString(
1143 utf8_string_object );
1144 #endif
1145 if( codepage_string == NULL )
1146 {
1147 return( -1 );
1148 }
1149 result = pycreg_file_set_ascii_codepage_from_string(
1150 pycreg_file,
1151 codepage_string );
1152
1153 if( result != 1 )
1154 {
1155 return( -1 );
1156 }
1157 return( 0 );
1158 }
1159 PyErr_Clear();
1160
1161 #if PY_MAJOR_VERSION >= 3
1162 result = PyObject_IsInstance(
1163 string_object,
1164 (PyObject *) &PyBytes_Type );
1165 #else
1166 result = PyObject_IsInstance(
1167 string_object,
1168 (PyObject *) &PyString_Type );
1169 #endif
1170 if( result == -1 )
1171 {
1172 pycreg_error_fetch_and_raise(
1173 PyExc_RuntimeError,
1174 "%s: unable to determine if string object is of type string.",
1175 function );
1176
1177 return( -1 );
1178 }
1179 else if( result != 0 )
1180 {
1181 #if PY_MAJOR_VERSION >= 3
1182 codepage_string = PyBytes_AsString(
1183 string_object );
1184 #else
1185 codepage_string = PyString_AsString(
1186 string_object );
1187 #endif
1188 if( codepage_string == NULL )
1189 {
1190 return( -1 );
1191 }
1192 result = pycreg_file_set_ascii_codepage_from_string(
1193 pycreg_file,
1194 codepage_string );
1195
1196 if( result != 1 )
1197 {
1198 return( -1 );
1199 }
1200 return( 0 );
1201 }
1202 PyErr_Format(
1203 PyExc_TypeError,
1204 "%s: unsupported string object type.",
1205 function );
1206
1207 return( -1 );
1208 }
1209
1210 /* Retrieves the format version
1211 * Returns a Python object if successful or NULL on error
1212 */
pycreg_file_get_format_version(pycreg_file_t * pycreg_file,PyObject * arguments PYCREG_ATTRIBUTE_UNUSED)1213 PyObject *pycreg_file_get_format_version(
1214 pycreg_file_t *pycreg_file,
1215 PyObject *arguments PYCREG_ATTRIBUTE_UNUSED )
1216 {
1217 char utf8_string[ 4 ];
1218
1219 PyObject *string_object = NULL;
1220 libcerror_error_t *error = NULL;
1221 const char *errors = NULL;
1222 static char *function = "pycreg_file_get_format_version";
1223 uint16_t major_version = 0;
1224 uint16_t minor_version = 0;
1225 int result = 0;
1226
1227 PYCREG_UNREFERENCED_PARAMETER( arguments )
1228
1229 if( pycreg_file == NULL )
1230 {
1231 PyErr_Format(
1232 PyExc_ValueError,
1233 "%s: invalid file.",
1234 function );
1235
1236 return( NULL );
1237 }
1238 Py_BEGIN_ALLOW_THREADS
1239
1240 result = libcreg_file_get_format_version(
1241 pycreg_file->file,
1242 &major_version,
1243 &minor_version,
1244 &error );
1245
1246 Py_END_ALLOW_THREADS
1247
1248 if( result != 1 )
1249 {
1250 pycreg_error_raise(
1251 error,
1252 PyExc_IOError,
1253 "%s: unable to retrieve format version.",
1254 function );
1255
1256 libcerror_error_free(
1257 &error );
1258
1259 return( NULL );
1260 }
1261 if( major_version > 9 )
1262 {
1263 PyErr_Format(
1264 PyExc_ValueError,
1265 "%s: major version out of bounds.",
1266 function );
1267
1268 return( NULL );
1269 }
1270 if( minor_version > 9 )
1271 {
1272 PyErr_Format(
1273 PyExc_ValueError,
1274 "%s: minor version out of bounds.",
1275 function );
1276
1277 return( NULL );
1278 }
1279 utf8_string[ 0 ] = '0' + (char) major_version;
1280 utf8_string[ 1 ] = '.';
1281 utf8_string[ 2 ] = '0' + (char) minor_version;
1282 utf8_string[ 3 ] = 0;
1283
1284 /* Pass the string length to PyUnicode_DecodeUTF8 otherwise it makes
1285 * the end of string character is part of the string.
1286 */
1287 string_object = PyUnicode_DecodeUTF8(
1288 utf8_string,
1289 (Py_ssize_t) 3,
1290 errors );
1291
1292 if( string_object == NULL )
1293 {
1294 PyErr_Format(
1295 PyExc_IOError,
1296 "%s: unable to convert UTF-8 string into Unicode object.",
1297 function );
1298
1299 return( NULL );
1300 }
1301 return( string_object );
1302 }
1303
1304 /* Retrieves the type
1305 * Returns a Python object if successful or NULL on error
1306 */
pycreg_file_get_type(pycreg_file_t * pycreg_file,PyObject * arguments PYCREG_ATTRIBUTE_UNUSED)1307 PyObject *pycreg_file_get_type(
1308 pycreg_file_t *pycreg_file,
1309 PyObject *arguments PYCREG_ATTRIBUTE_UNUSED )
1310 {
1311 PyObject *integer_object = NULL;
1312 libcerror_error_t *error = NULL;
1313 static char *function = "pycreg_file_get_type";
1314 uint32_t value_32bit = 0;
1315 int result = 0;
1316
1317 PYCREG_UNREFERENCED_PARAMETER( arguments )
1318
1319 if( pycreg_file == NULL )
1320 {
1321 PyErr_Format(
1322 PyExc_ValueError,
1323 "%s: invalid file.",
1324 function );
1325
1326 return( NULL );
1327 }
1328 Py_BEGIN_ALLOW_THREADS
1329
1330 result = libcreg_file_get_type(
1331 pycreg_file->file,
1332 &value_32bit,
1333 &error );
1334
1335 Py_END_ALLOW_THREADS
1336
1337 if( result != 1 )
1338 {
1339 pycreg_error_raise(
1340 error,
1341 PyExc_IOError,
1342 "%s: unable to retrieve type.",
1343 function );
1344
1345 libcerror_error_free(
1346 &error );
1347
1348 return( NULL );
1349 }
1350 integer_object = PyLong_FromUnsignedLong(
1351 (unsigned long) value_32bit );
1352
1353 return( integer_object );
1354 }
1355
1356 /* Retrieves the root key
1357 * Returns a Python object if successful or NULL on error
1358 */
pycreg_file_get_root_key(pycreg_file_t * pycreg_file,PyObject * arguments PYCREG_ATTRIBUTE_UNUSED)1359 PyObject *pycreg_file_get_root_key(
1360 pycreg_file_t *pycreg_file,
1361 PyObject *arguments PYCREG_ATTRIBUTE_UNUSED )
1362 {
1363 PyObject *key_object = NULL;
1364 libcerror_error_t *error = NULL;
1365 libcreg_key_t *root_key = NULL;
1366 static char *function = "pycreg_file_get_root_key";
1367 int result = 0;
1368
1369 PYCREG_UNREFERENCED_PARAMETER( arguments )
1370
1371 if( pycreg_file == NULL )
1372 {
1373 PyErr_Format(
1374 PyExc_ValueError,
1375 "%s: invalid file.",
1376 function );
1377
1378 return( NULL );
1379 }
1380 Py_BEGIN_ALLOW_THREADS
1381
1382 result = libcreg_file_get_root_key(
1383 pycreg_file->file,
1384 &root_key,
1385 &error );
1386
1387 Py_END_ALLOW_THREADS
1388
1389 if( result == -1 )
1390 {
1391 pycreg_error_raise(
1392 error,
1393 PyExc_IOError,
1394 "%s: unable to retrieve root key.",
1395 function );
1396
1397 libcerror_error_free(
1398 &error );
1399
1400 goto on_error;
1401 }
1402 else if( result == 0 )
1403 {
1404 Py_IncRef(
1405 Py_None );
1406
1407 return( Py_None );
1408 }
1409 key_object = pycreg_key_new(
1410 root_key,
1411 (PyObject *) pycreg_file );
1412
1413 if( key_object == NULL )
1414 {
1415 PyErr_Format(
1416 PyExc_MemoryError,
1417 "%s: unable to create root key object.",
1418 function );
1419
1420 goto on_error;
1421 }
1422 return( key_object );
1423
1424 on_error:
1425 if( root_key != NULL )
1426 {
1427 libcreg_key_free(
1428 &root_key,
1429 NULL );
1430 }
1431 return( NULL );
1432 }
1433
1434 /* Retrieves the key specified by the path
1435 * Returns a Python object if successful or NULL on error
1436 */
pycreg_file_get_key_by_path(pycreg_file_t * pycreg_file,PyObject * arguments,PyObject * keywords)1437 PyObject *pycreg_file_get_key_by_path(
1438 pycreg_file_t *pycreg_file,
1439 PyObject *arguments,
1440 PyObject *keywords )
1441 {
1442 PyObject *key_object = NULL;
1443 libcerror_error_t *error = NULL;
1444 libcreg_key_t *key = NULL;
1445 static char *function = "pycreg_file_get_key_by_path";
1446 static char *keyword_list[] = { "path", NULL };
1447 char *utf8_path = NULL;
1448 size_t utf8_path_length = 0;
1449 int result = 0;
1450
1451 if( pycreg_file == NULL )
1452 {
1453 PyErr_Format(
1454 PyExc_ValueError,
1455 "%s: invalid file.",
1456 function );
1457
1458 return( NULL );
1459 }
1460 if( PyArg_ParseTupleAndKeywords(
1461 arguments,
1462 keywords,
1463 "s",
1464 keyword_list,
1465 &utf8_path ) == 0 )
1466 {
1467 goto on_error;
1468 }
1469 utf8_path_length = narrow_string_length(
1470 utf8_path );
1471
1472 Py_BEGIN_ALLOW_THREADS
1473
1474 result = libcreg_file_get_key_by_utf8_path(
1475 pycreg_file->file,
1476 (uint8_t *) utf8_path,
1477 utf8_path_length,
1478 &key,
1479 &error );
1480
1481 Py_END_ALLOW_THREADS
1482
1483 if( result == -1 )
1484 {
1485 pycreg_error_raise(
1486 error,
1487 PyExc_IOError,
1488 "%s: unable to retrieve key.",
1489 function );
1490
1491 libcerror_error_free(
1492 &error );
1493
1494 goto on_error;
1495 }
1496 else if( result == 0 )
1497 {
1498 Py_IncRef(
1499 Py_None );
1500
1501 return( Py_None );
1502 }
1503 key_object = pycreg_key_new(
1504 key,
1505 (PyObject *) pycreg_file );
1506
1507 if( key_object == NULL )
1508 {
1509 PyErr_Format(
1510 PyExc_MemoryError,
1511 "%s: unable to create key object.",
1512 function );
1513
1514 goto on_error;
1515 }
1516 return( key_object );
1517
1518 on_error:
1519 if( key != NULL )
1520 {
1521 libcreg_key_free(
1522 &key,
1523 NULL );
1524 }
1525 return( NULL );
1526 }
1527
1528