1 /*
2 * Python object wrapper of libfwsi_item_t type LIBFWSI_ITEM_TYPE_VOLUME
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 <types.h>
24
25 #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI )
26 #include <stdlib.h>
27 #endif
28
29 #include "pyfwsi_error.h"
30 #include "pyfwsi_guid.h"
31 #include "pyfwsi_item.h"
32 #include "pyfwsi_libcerror.h"
33 #include "pyfwsi_libfwsi.h"
34 #include "pyfwsi_python.h"
35 #include "pyfwsi_unused.h"
36 #include "pyfwsi_volume.h"
37
38 PyMethodDef pyfwsi_volume_object_methods[] = {
39
40 { "get_name",
41 (PyCFunction) pyfwsi_volume_get_name,
42 METH_NOARGS,
43 "get_name() -> Unicode string\n"
44 "\n"
45 "Retrieves the name." },
46
47 { "get_identifier",
48 (PyCFunction) pyfwsi_volume_get_identifier,
49 METH_NOARGS,
50 "get_identifier() -> Unicode string\n"
51 "\n"
52 "Retrieves the identifier." },
53
54 { "get_shell_folder_identifier",
55 (PyCFunction) pyfwsi_volume_get_shell_folder_identifier,
56 METH_NOARGS,
57 "get_shell_folder_identifier() -> Unicode string\n"
58 "\n"
59 "Retrieves the shell folder identifier." },
60
61 /* Sentinel */
62 { NULL, NULL, 0, NULL }
63 };
64
65 PyGetSetDef pyfwsi_volume_object_get_set_definitions[] = {
66
67 { "name",
68 (getter) pyfwsi_volume_get_name,
69 (setter) 0,
70 "The name.",
71 NULL },
72
73 { "identifier",
74 (getter) pyfwsi_volume_get_identifier,
75 (setter) 0,
76 "The identifier.",
77 NULL },
78
79 { "shell_folder_identifier",
80 (getter) pyfwsi_volume_get_shell_folder_identifier,
81 (setter) 0,
82 "The shell folder identifier.",
83 NULL },
84
85 /* Sentinel */
86 { NULL, NULL, NULL, NULL, NULL }
87 };
88
89 PyTypeObject pyfwsi_volume_type_object = {
90 PyVarObject_HEAD_INIT( NULL, 0 )
91
92 /* tp_name */
93 "pyfwsi.volume",
94 /* tp_basicsize */
95 sizeof( pyfwsi_item_t ),
96 /* tp_itemsize */
97 0,
98 /* tp_dealloc */
99 0,
100 /* tp_print */
101 0,
102 /* tp_getattr */
103 0,
104 /* tp_setattr */
105 0,
106 /* tp_compare */
107 0,
108 /* tp_repr */
109 0,
110 /* tp_as_number */
111 0,
112 /* tp_as_sequence */
113 0,
114 /* tp_as_mapping */
115 0,
116 /* tp_hash */
117 0,
118 /* tp_call */
119 0,
120 /* tp_str */
121 0,
122 /* tp_getattro */
123 0,
124 /* tp_setattro */
125 0,
126 /* tp_as_buffer */
127 0,
128 /* tp_flags */
129 Py_TPFLAGS_DEFAULT,
130 /* tp_doc */
131 "pyfwsi volume object (wraps libfwsi_item_t type LIBFWSI_ITEM_TYPE_VOLUME)",
132 /* tp_traverse */
133 0,
134 /* tp_clear */
135 0,
136 /* tp_richcompare */
137 0,
138 /* tp_weaklistoffset */
139 0,
140 /* tp_iter */
141 0,
142 /* tp_iternext */
143 0,
144 /* tp_methods */
145 pyfwsi_volume_object_methods,
146 /* tp_members */
147 0,
148 /* tp_getset */
149 pyfwsi_volume_object_get_set_definitions,
150 /* tp_base */
151 &pyfwsi_item_type_object,
152 /* tp_dict */
153 0,
154 /* tp_descr_get */
155 0,
156 /* tp_descr_set */
157 0,
158 /* tp_dictoffset */
159 0,
160 /* tp_init */
161 0,
162 /* tp_alloc */
163 0,
164 /* tp_new */
165 0,
166 /* tp_free */
167 0,
168 /* tp_is_gc */
169 0,
170 /* tp_bases */
171 NULL,
172 /* tp_mro */
173 NULL,
174 /* tp_cache */
175 NULL,
176 /* tp_subclasses */
177 NULL,
178 /* tp_weaklist */
179 NULL,
180 /* tp_del */
181 0
182 };
183
184 /* Retrieves the name
185 * Returns a Python object if successful or NULL on error
186 */
pyfwsi_volume_get_name(pyfwsi_item_t * pyfwsi_item,PyObject * arguments PYFWSI_ATTRIBUTE_UNUSED)187 PyObject *pyfwsi_volume_get_name(
188 pyfwsi_item_t *pyfwsi_item,
189 PyObject *arguments PYFWSI_ATTRIBUTE_UNUSED )
190 {
191 PyObject *string_object = NULL;
192 libcerror_error_t *error = NULL;
193 const char *errors = NULL;
194 static char *function = "pyfwsi_volume_get_name";
195 char *utf8_string = NULL;
196 size_t utf8_string_size = 0;
197 int result = 0;
198
199 PYFWSI_UNREFERENCED_PARAMETER( arguments )
200
201 if( pyfwsi_item == NULL )
202 {
203 PyErr_Format(
204 PyExc_ValueError,
205 "%s: invalid item.",
206 function );
207
208 return( NULL );
209 }
210 Py_BEGIN_ALLOW_THREADS
211
212 result = libfwsi_volume_get_utf8_name_size(
213 pyfwsi_item->item,
214 &utf8_string_size,
215 &error );
216
217 Py_END_ALLOW_THREADS
218
219 if( result == -1 )
220 {
221 pyfwsi_error_raise(
222 error,
223 PyExc_IOError,
224 "%s: unable to determine size of name as UTF-8 string.",
225 function );
226
227 libcerror_error_free(
228 &error );
229
230 goto on_error;
231 }
232 else if( ( result == 0 )
233 || ( utf8_string_size == 0 ) )
234 {
235 Py_IncRef(
236 Py_None );
237
238 return( Py_None );
239 }
240 utf8_string = (char *) PyMem_Malloc(
241 sizeof( char ) * utf8_string_size );
242
243 if( utf8_string == NULL )
244 {
245 PyErr_Format(
246 PyExc_MemoryError,
247 "%s: unable to create UTF-8 string.",
248 function );
249
250 goto on_error;
251 }
252 Py_BEGIN_ALLOW_THREADS
253
254 result = libfwsi_volume_get_utf8_name(
255 pyfwsi_item->item,
256 (uint8_t *) utf8_string,
257 utf8_string_size,
258 &error );
259
260 Py_END_ALLOW_THREADS
261
262 if( result != 1 )
263 {
264 pyfwsi_error_raise(
265 error,
266 PyExc_IOError,
267 "%s: unable to retrieve name as UTF-8 string.",
268 function );
269
270 libcerror_error_free(
271 &error );
272
273 goto on_error;
274 }
275 /* Pass the string length to PyUnicode_DecodeUTF8 otherwise it makes
276 * the end of string character is part of the string
277 */
278 string_object = PyUnicode_DecodeUTF8(
279 utf8_string,
280 (Py_ssize_t) utf8_string_size - 1,
281 errors );
282
283 if( string_object == NULL )
284 {
285 PyErr_Format(
286 PyExc_IOError,
287 "%s: unable to convert UTF-8 string into Unicode object.",
288 function );
289
290 goto on_error;
291 }
292 PyMem_Free(
293 utf8_string );
294
295 return( string_object );
296
297 on_error:
298 if( utf8_string != NULL )
299 {
300 PyMem_Free(
301 utf8_string );
302 }
303 return( NULL );
304 }
305
306 /* Retrieves the identifier
307 * Returns a Python object if successful or NULL on error
308 */
pyfwsi_volume_get_identifier(pyfwsi_item_t * pyfwsi_item,PyObject * arguments PYFWSI_ATTRIBUTE_UNUSED)309 PyObject *pyfwsi_volume_get_identifier(
310 pyfwsi_item_t *pyfwsi_item,
311 PyObject *arguments PYFWSI_ATTRIBUTE_UNUSED )
312 {
313 uint8_t guid_data[ 16 ];
314
315 PyObject *string_object = NULL;
316 libcerror_error_t *error = NULL;
317 static char *function = "pyfwsi_volume_get_identifier";
318 int result = 0;
319
320 PYFWSI_UNREFERENCED_PARAMETER( arguments )
321
322 if( pyfwsi_item == NULL )
323 {
324 PyErr_Format(
325 PyExc_TypeError,
326 "%s: invalid item.",
327 function );
328
329 return( NULL );
330 }
331 Py_BEGIN_ALLOW_THREADS
332
333 result = libfwsi_volume_get_identifier(
334 pyfwsi_item->item,
335 guid_data,
336 16,
337 &error );
338
339 Py_END_ALLOW_THREADS
340
341 if( result != 1 )
342 {
343 pyfwsi_error_raise(
344 error,
345 PyExc_IOError,
346 "%s: unable to retrieve identifier.",
347 function );
348
349 libcerror_error_free(
350 &error );
351
352 return( NULL );
353 }
354 string_object = pyfwsi_string_new_from_guid(
355 guid_data,
356 16 );
357
358 if( string_object == NULL )
359 {
360 PyErr_Format(
361 PyExc_IOError,
362 "%s: unable to convert GUID into Unicode object.",
363 function );
364
365 return( NULL );
366 }
367 return( string_object );
368 }
369
370 /* Retrieves the shell folder identifier
371 * Returns a Python object if successful or NULL on error
372 */
pyfwsi_volume_get_shell_folder_identifier(pyfwsi_item_t * pyfwsi_item,PyObject * arguments PYFWSI_ATTRIBUTE_UNUSED)373 PyObject *pyfwsi_volume_get_shell_folder_identifier(
374 pyfwsi_item_t *pyfwsi_item,
375 PyObject *arguments PYFWSI_ATTRIBUTE_UNUSED )
376 {
377 uint8_t guid_data[ 16 ];
378
379 PyObject *string_object = NULL;
380 libcerror_error_t *error = NULL;
381 static char *function = "pyfwsi_volume_get_shell_folder_identifier";
382 int result = 0;
383
384 PYFWSI_UNREFERENCED_PARAMETER( arguments )
385
386 if( pyfwsi_item == NULL )
387 {
388 PyErr_Format(
389 PyExc_TypeError,
390 "%s: invalid item.",
391 function );
392
393 return( NULL );
394 }
395 Py_BEGIN_ALLOW_THREADS
396
397 result = libfwsi_volume_get_shell_folder_identifier(
398 pyfwsi_item->item,
399 guid_data,
400 16,
401 &error );
402
403 Py_END_ALLOW_THREADS
404
405 if( result != 1 )
406 {
407 pyfwsi_error_raise(
408 error,
409 PyExc_IOError,
410 "%s: unable to retrieve shell folder identifier.",
411 function );
412
413 libcerror_error_free(
414 &error );
415
416 return( NULL );
417 }
418 string_object = pyfwsi_string_new_from_guid(
419 guid_data,
420 16 );
421
422 if( string_object == NULL )
423 {
424 PyErr_Format(
425 PyExc_IOError,
426 "%s: unable to convert GUID into Unicode object.",
427 function );
428
429 return( NULL );
430 }
431 return( string_object );
432 }
433
434