/src/libregf/libregf/libregf_value_key.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Value key functions |
3 | | * |
4 | | * Copyright (C) 2009-2024, 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 | | #if defined( HAVE_WCTYPE_H ) |
28 | | #include <wctype.h> |
29 | | #endif |
30 | | |
31 | | #include "libregf_data_type.h" |
32 | | #include "libregf_debug.h" |
33 | | #include "libregf_definitions.h" |
34 | | #include "libregf_io_handle.h" |
35 | | #include "libregf_libcerror.h" |
36 | | #include "libregf_libcnotify.h" |
37 | | #include "libregf_libuna.h" |
38 | | #include "libregf_value_key.h" |
39 | | #include "libregf_unused.h" |
40 | | |
41 | | #include "regf_cell_values.h" |
42 | | |
43 | | /* Creates a value key |
44 | | * Make sure the value value_key is referencing, is set to NULL |
45 | | * Returns 1 if successful or -1 on error |
46 | | */ |
47 | | int libregf_value_key_initialize( |
48 | | libregf_value_key_t **value_key, |
49 | | libcerror_error_t **error ) |
50 | 589 | { |
51 | 589 | static char *function = "libregf_value_key_initialize"; |
52 | | |
53 | 589 | if( value_key == NULL ) |
54 | 0 | { |
55 | 0 | libcerror_error_set( |
56 | 0 | error, |
57 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
58 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
59 | 0 | "%s: invalid value key.", |
60 | 0 | function ); |
61 | |
|
62 | 0 | return( -1 ); |
63 | 0 | } |
64 | 589 | if( *value_key != NULL ) |
65 | 0 | { |
66 | 0 | libcerror_error_set( |
67 | 0 | error, |
68 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
69 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
70 | 0 | "%s: invalid value key value already set.", |
71 | 0 | function ); |
72 | |
|
73 | 0 | return( -1 ); |
74 | 0 | } |
75 | 589 | *value_key = memory_allocate_structure( |
76 | 589 | libregf_value_key_t ); |
77 | | |
78 | 589 | if( *value_key == NULL ) |
79 | 0 | { |
80 | 0 | libcerror_error_set( |
81 | 0 | error, |
82 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
83 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
84 | 0 | "%s: unable to create value key.", |
85 | 0 | function ); |
86 | |
|
87 | 0 | goto on_error; |
88 | 0 | } |
89 | 589 | if( memory_set( |
90 | 589 | *value_key, |
91 | 589 | 0, |
92 | 589 | sizeof( libregf_value_key_t ) ) == NULL ) |
93 | 0 | { |
94 | 0 | libcerror_error_set( |
95 | 0 | error, |
96 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
97 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
98 | 0 | "%s: unable to clear value key.", |
99 | 0 | function ); |
100 | |
|
101 | 0 | goto on_error; |
102 | 0 | } |
103 | 589 | return( 1 ); |
104 | | |
105 | 0 | on_error: |
106 | 0 | if( *value_key != NULL ) |
107 | 0 | { |
108 | 0 | memory_free( |
109 | 0 | *value_key ); |
110 | |
|
111 | 0 | *value_key = NULL; |
112 | 0 | } |
113 | 0 | return( -1 ); |
114 | 589 | } |
115 | | |
116 | | /* Frees a value key |
117 | | * Returns 1 if successful or -1 on error |
118 | | */ |
119 | | int libregf_value_key_free( |
120 | | libregf_value_key_t **value_key, |
121 | | libcerror_error_t **error ) |
122 | 589 | { |
123 | 589 | static char *function = "libregf_value_key_free"; |
124 | | |
125 | 589 | if( value_key == NULL ) |
126 | 0 | { |
127 | 0 | libcerror_error_set( |
128 | 0 | error, |
129 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
130 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
131 | 0 | "%s: invalid value key.", |
132 | 0 | function ); |
133 | |
|
134 | 0 | return( -1 ); |
135 | 0 | } |
136 | 589 | if( *value_key != NULL ) |
137 | 589 | { |
138 | 589 | if( ( *value_key )->name != NULL ) |
139 | 246 | { |
140 | 246 | memory_free( |
141 | 246 | ( *value_key )->name ); |
142 | 246 | } |
143 | 589 | if( ( *value_key )->data != NULL ) |
144 | 0 | { |
145 | 0 | memory_free( |
146 | 0 | ( *value_key )->data ); |
147 | 0 | } |
148 | 589 | memory_free( |
149 | 589 | *value_key ); |
150 | | |
151 | 589 | *value_key = NULL; |
152 | 589 | } |
153 | 589 | return( 1 ); |
154 | 589 | } |
155 | | |
156 | | /* Clones (duplicates) the value key |
157 | | * Returns 1 if successful or -1 on error |
158 | | */ |
159 | | int libregf_value_key_clone( |
160 | | libregf_value_key_t **destination_value_key, |
161 | | libregf_value_key_t *source_value_key, |
162 | | libcerror_error_t **error ) |
163 | 239 | { |
164 | 239 | static char *function = "libregf_value_key_clone"; |
165 | | |
166 | 239 | if( destination_value_key == NULL ) |
167 | 0 | { |
168 | 0 | libcerror_error_set( |
169 | 0 | error, |
170 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
171 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
172 | 0 | "%s: invalid destination value key.", |
173 | 0 | function ); |
174 | |
|
175 | 0 | return( -1 ); |
176 | 0 | } |
177 | 239 | if( *destination_value_key != NULL ) |
178 | 0 | { |
179 | 0 | libcerror_error_set( |
180 | 0 | error, |
181 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
182 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
183 | 0 | "%s: destination value key already set.", |
184 | 0 | function ); |
185 | |
|
186 | 0 | return( -1 ); |
187 | 0 | } |
188 | 239 | if( source_value_key == NULL ) |
189 | 2 | { |
190 | 2 | *destination_value_key = NULL; |
191 | | |
192 | 2 | return( 1 ); |
193 | 2 | } |
194 | 237 | if( libregf_value_key_initialize( |
195 | 237 | destination_value_key, |
196 | 237 | error ) != 1 ) |
197 | 0 | { |
198 | 0 | libcerror_error_set( |
199 | 0 | error, |
200 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
201 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
202 | 0 | "%s: unable to create destination value key.", |
203 | 0 | function ); |
204 | |
|
205 | 0 | goto on_error; |
206 | 0 | } |
207 | 237 | if( source_value_key->name != NULL ) |
208 | 114 | { |
209 | 114 | if( source_value_key->name_size == 0 ) |
210 | 0 | { |
211 | 0 | libcerror_error_set( |
212 | 0 | error, |
213 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
214 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
215 | 0 | "%s: invalid source value key - invalid name size value out of bounds.", |
216 | 0 | function ); |
217 | |
|
218 | 0 | goto on_error; |
219 | 0 | } |
220 | 114 | ( *destination_value_key )->name = (uint8_t *) memory_allocate( |
221 | 114 | sizeof( uint8_t ) * (size_t) source_value_key->name_size ); |
222 | | |
223 | 114 | if( ( *destination_value_key )->name == NULL ) |
224 | 0 | { |
225 | 0 | libcerror_error_set( |
226 | 0 | error, |
227 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
228 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
229 | 0 | "%s: unable to create value name.", |
230 | 0 | function ); |
231 | |
|
232 | 0 | goto on_error; |
233 | 0 | } |
234 | 114 | if( memory_copy( |
235 | 114 | ( *destination_value_key )->name, |
236 | 114 | source_value_key->name, |
237 | 114 | (size_t) source_value_key->name_size ) == NULL ) |
238 | 0 | { |
239 | 0 | libcerror_error_set( |
240 | 0 | error, |
241 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
242 | 0 | LIBCERROR_MEMORY_ERROR_COPY_FAILED, |
243 | 0 | "%s: unable to copy value name.", |
244 | 0 | function ); |
245 | |
|
246 | 0 | goto on_error; |
247 | 0 | } |
248 | 114 | ( *destination_value_key )->name_size = source_value_key->name_size; |
249 | 114 | ( *destination_value_key )->name_hash = source_value_key->name_hash; |
250 | 114 | } |
251 | 237 | if( source_value_key->data != NULL ) |
252 | 0 | { |
253 | 0 | if( ( source_value_key->data_size == 0 ) |
254 | 0 | || ( source_value_key->data_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) |
255 | 0 | { |
256 | 0 | libcerror_error_set( |
257 | 0 | error, |
258 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
259 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
260 | 0 | "%s: invalid source value key - invalid data size value out of bounds.", |
261 | 0 | function ); |
262 | |
|
263 | 0 | goto on_error; |
264 | 0 | } |
265 | 0 | ( *destination_value_key )->data = (uint8_t *) memory_allocate( |
266 | 0 | sizeof( uint8_t ) * (size_t) source_value_key->data_size ); |
267 | |
|
268 | 0 | if( ( *destination_value_key )->data == NULL ) |
269 | 0 | { |
270 | 0 | libcerror_error_set( |
271 | 0 | error, |
272 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
273 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
274 | 0 | "%s: unable to create value data.", |
275 | 0 | function ); |
276 | |
|
277 | 0 | goto on_error; |
278 | 0 | } |
279 | 0 | if( memory_copy( |
280 | 0 | ( *destination_value_key )->data, |
281 | 0 | source_value_key->data, |
282 | 0 | (size_t) source_value_key->data_size ) == NULL ) |
283 | 0 | { |
284 | 0 | libcerror_error_set( |
285 | 0 | error, |
286 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
287 | 0 | LIBCERROR_MEMORY_ERROR_COPY_FAILED, |
288 | 0 | "%s: unable to copy value data.", |
289 | 0 | function ); |
290 | |
|
291 | 0 | goto on_error; |
292 | 0 | } |
293 | 0 | ( *destination_value_key )->data_size = source_value_key->data_size; |
294 | 0 | } |
295 | 237 | ( *destination_value_key )->value_type = source_value_key->value_type; |
296 | 237 | ( *destination_value_key )->flags = source_value_key->flags; |
297 | 237 | ( *destination_value_key )->data_offset = source_value_key->data_offset; |
298 | 237 | ( *destination_value_key )->data_in_key = source_value_key->data_in_key; |
299 | | |
300 | 237 | return( 1 ); |
301 | | |
302 | 0 | on_error: |
303 | 0 | libregf_value_key_free( |
304 | 0 | destination_value_key, |
305 | 0 | NULL ); |
306 | |
|
307 | 0 | return( -1 ); |
308 | 237 | } |
309 | | |
310 | | /* Reads a value key |
311 | | * Returns 1 if successful, 0 if the signature does not match or -1 on error |
312 | | */ |
313 | | int libregf_value_key_read_data( |
314 | | libregf_value_key_t *value_key, |
315 | | libregf_io_handle_t *io_handle, |
316 | | const uint8_t *data, |
317 | | size_t data_size, |
318 | | uint32_t value_key_hash LIBREGF_ATTRIBUTE_UNUSED, |
319 | | libcerror_error_t **error ) |
320 | 352 | { |
321 | 352 | static char *function = "libregf_value_key_read_data"; |
322 | 352 | libuna_unicode_character_t unicode_character = 0; |
323 | 352 | size_t data_offset = 0; |
324 | 352 | size_t name_index = 0; |
325 | 352 | size_t value_key_data_size = 0; |
326 | 352 | uint32_t value_data_offset = 0; |
327 | 352 | uint8_t correct_string_size = 0; |
328 | 352 | int result = 0; |
329 | | |
330 | | #if defined( HAVE_DEBUG_OUTPUT ) |
331 | | uint32_t value_32bit = 0; |
332 | | uint16_t value_16bit = 0; |
333 | | #endif |
334 | | |
335 | 352 | LIBREGF_UNREFERENCED_PARAMETER( value_key_hash ) |
336 | | |
337 | 352 | if( value_key == NULL ) |
338 | 0 | { |
339 | 0 | libcerror_error_set( |
340 | 0 | error, |
341 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
342 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
343 | 0 | "%s: invalid value key.", |
344 | 0 | function ); |
345 | |
|
346 | 0 | return( -1 ); |
347 | 0 | } |
348 | 352 | if( value_key->name != NULL ) |
349 | 0 | { |
350 | 0 | libcerror_error_set( |
351 | 0 | error, |
352 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
353 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
354 | 0 | "%s: invalid value key - name value already set.", |
355 | 0 | function ); |
356 | |
|
357 | 0 | return( -1 ); |
358 | 0 | } |
359 | 352 | if( value_key->data != NULL ) |
360 | 0 | { |
361 | 0 | libcerror_error_set( |
362 | 0 | error, |
363 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
364 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
365 | 0 | "%s: invalid value key - data value already set.", |
366 | 0 | function ); |
367 | |
|
368 | 0 | return( -1 ); |
369 | 0 | } |
370 | 352 | if( io_handle == NULL ) |
371 | 0 | { |
372 | 0 | libcerror_error_set( |
373 | 0 | error, |
374 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
375 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
376 | 0 | "%s: invalid IO handle.", |
377 | 0 | function ); |
378 | |
|
379 | 0 | return( -1 ); |
380 | 0 | } |
381 | 352 | value_key_data_size = sizeof( regf_value_key_t ); |
382 | | |
383 | 352 | if( ( io_handle->major_version == 1 ) |
384 | 352 | && ( io_handle->minor_version <= 1 ) ) |
385 | 0 | { |
386 | 0 | value_key_data_size += 4; |
387 | 0 | } |
388 | 352 | if( data == NULL ) |
389 | 0 | { |
390 | 0 | libcerror_error_set( |
391 | 0 | error, |
392 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
393 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
394 | 0 | "%s: invalid data.", |
395 | 0 | function ); |
396 | |
|
397 | 0 | return( -1 ); |
398 | 0 | } |
399 | 352 | if( ( data_size < value_key_data_size ) |
400 | 352 | || ( data_size > (size_t) SSIZE_MAX ) ) |
401 | 0 | { |
402 | 0 | libcerror_error_set( |
403 | 0 | error, |
404 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
405 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, |
406 | 0 | "%s: invalid data size value out of bounds.", |
407 | 0 | function ); |
408 | |
|
409 | 0 | return( -1 ); |
410 | 0 | } |
411 | | #if defined( HAVE_DEBUG_OUTPUT ) |
412 | | if( libcnotify_verbose != 0 ) |
413 | | { |
414 | | libcnotify_printf( |
415 | | "%s: value key data:\n", |
416 | | function ); |
417 | | libcnotify_print_data( |
418 | | data, |
419 | | data_size, |
420 | | LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); |
421 | | } |
422 | | #endif |
423 | 352 | if( ( io_handle->major_version == 1 ) |
424 | 352 | && ( io_handle->minor_version <= 1 ) ) |
425 | 0 | { |
426 | 0 | data_offset += 4; |
427 | 0 | } |
428 | | /* Check if the signature matches that of a value key: "vk" |
429 | | */ |
430 | 352 | if( ( data[ data_offset ] != (uint8_t) 'v' ) |
431 | 352 | || ( data[ data_offset + 1 ] != (uint8_t) 'k' ) ) |
432 | 54 | { |
433 | 54 | return( 0 ); |
434 | 54 | } |
435 | 298 | byte_stream_copy_to_uint16_little_endian( |
436 | 298 | ( (regf_value_key_t *) &( data[ data_offset ] ) )->value_name_size, |
437 | 298 | value_key->name_size ); |
438 | | |
439 | 298 | byte_stream_copy_to_uint32_little_endian( |
440 | 298 | ( (regf_value_key_t *) &( data[ data_offset ] ) )->data_size, |
441 | 298 | value_key->data_size ); |
442 | | |
443 | 298 | byte_stream_copy_to_uint32_little_endian( |
444 | 298 | ( (regf_value_key_t *) &( data[ data_offset ] ) )->data_offset, |
445 | 298 | value_data_offset ); |
446 | | |
447 | 298 | byte_stream_copy_to_uint32_little_endian( |
448 | 298 | ( (regf_value_key_t *) &( data[ data_offset ] ) )->value_type, |
449 | 298 | value_key->value_type ); |
450 | | |
451 | 298 | byte_stream_copy_to_uint16_little_endian( |
452 | 298 | ( (regf_value_key_t *) &( data[ data_offset ] ) )->flags, |
453 | 298 | value_key->flags ); |
454 | | |
455 | | #if defined( HAVE_DEBUG_OUTPUT ) |
456 | | if( libcnotify_verbose != 0 ) |
457 | | { |
458 | | if( ( io_handle->major_version == 1 ) |
459 | | && ( io_handle->minor_version <= 1 ) ) |
460 | | { |
461 | | byte_stream_copy_to_uint32_little_endian( |
462 | | data, |
463 | | value_32bit ); |
464 | | libcnotify_printf( |
465 | | "%s: unknown0\t\t\t\t\t: 0x%08" PRIx32 " (%" PRIi32 ")\n", |
466 | | function, |
467 | | value_32bit, |
468 | | (int32_t) value_32bit ); |
469 | | } |
470 | | libcnotify_printf( |
471 | | "%s: signature\t\t\t\t\t: %c%c\n", |
472 | | function, |
473 | | ( (regf_value_key_t *) &( data[ data_offset ] ) )->signature[ 0 ], |
474 | | ( (regf_value_key_t *) &( data[ data_offset ] ) )->signature[ 1 ] ); |
475 | | |
476 | | libcnotify_printf( |
477 | | "%s: value name size\t\t\t\t: %" PRIu16 "\n", |
478 | | function, |
479 | | value_key->name_size ); |
480 | | |
481 | | libcnotify_printf( |
482 | | "%s: value data size\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n", |
483 | | function, |
484 | | value_key->data_size, |
485 | | value_key->data_size & 0x5fffffffUL ); |
486 | | |
487 | | if( ( value_key->data_size & 0x80000000UL ) == 0 ) |
488 | | { |
489 | | libcnotify_printf( |
490 | | "%s: value data offset\t\t\t\t: 0x%08" PRIx32 "\n", |
491 | | function, |
492 | | value_data_offset ); |
493 | | } |
494 | | else |
495 | | { |
496 | | libcnotify_printf( |
497 | | "%s: value data:\n", |
498 | | function ); |
499 | | libcnotify_print_data( |
500 | | ( (regf_value_key_t *) &( data[ data_offset ] ) )->data_offset, |
501 | | 4, |
502 | | 0 ); |
503 | | } |
504 | | libcnotify_printf( |
505 | | "%s: value type\t\t\t\t\t: 0x%08" PRIx32 " (%s) %s\n", |
506 | | function, |
507 | | value_key->value_type, |
508 | | libregf_data_type_get_identifier( |
509 | | value_key->value_type ), |
510 | | libregf_data_type_get_description( |
511 | | value_key->value_type ) ); |
512 | | |
513 | | libcnotify_printf( |
514 | | "%s: flags\t\t\t\t\t: 0x%04" PRIx16 "\n", |
515 | | function, |
516 | | value_key->flags ); |
517 | | libregf_debug_print_value_key_flags( |
518 | | value_key->flags ); |
519 | | |
520 | | byte_stream_copy_to_uint16_little_endian( |
521 | | ( (regf_value_key_t *) &( data[ data_offset ] ) )->unknown1, |
522 | | value_16bit ); |
523 | | libcnotify_printf( |
524 | | "%s: unknown1\t\t\t\t\t: 0x%04" PRIx16 " (%" PRIu16 ")\n", |
525 | | function, |
526 | | value_16bit, |
527 | | value_16bit ); |
528 | | } |
529 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
530 | | |
531 | 298 | if( ( value_key->data_size & 0x80000000UL ) != 0 ) |
532 | 95 | { |
533 | 95 | value_key->data_in_key = 1; |
534 | 95 | } |
535 | | /* TODO should this bitmask be 0x5fffffffUL ? */ |
536 | 298 | value_key->data_size &= 0x7fffffffUL; |
537 | | |
538 | 298 | if( value_key->data_in_key == 0 ) |
539 | 203 | { |
540 | 203 | value_key->data_offset = value_data_offset; |
541 | 203 | } |
542 | 95 | else |
543 | 95 | { |
544 | | /* TODO mark value as corrupted and handle issue */ |
545 | 95 | if( value_key->data_size > 4 ) |
546 | 47 | { |
547 | 47 | libcerror_error_set( |
548 | 47 | error, |
549 | 47 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
550 | 47 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
551 | 47 | "%s: invalid value data size value out of bounds.", |
552 | 47 | function ); |
553 | | |
554 | 47 | goto on_error; |
555 | 47 | } |
556 | 48 | if( value_key->data_size > 0 ) |
557 | 46 | { |
558 | 46 | if( ( value_key->value_type == LIBREGF_VALUE_TYPE_STRING ) |
559 | 46 | || ( value_key->value_type == LIBREGF_VALUE_TYPE_EXPANDABLE_STRING ) ) |
560 | 5 | { |
561 | 5 | if( ( value_key->data_size == 1 ) |
562 | 5 | || ( value_key->data_size == 3 ) ) |
563 | 2 | { |
564 | 2 | correct_string_size = 1; |
565 | | |
566 | 2 | value_key->data_size += 1; |
567 | 2 | } |
568 | 5 | } |
569 | 46 | if( value_key->data_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) |
570 | 0 | { |
571 | 0 | libcerror_error_set( |
572 | 0 | error, |
573 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
574 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, |
575 | 0 | "%s: invalid value key - invalid data size value exceeds maximum allocation size.", |
576 | 0 | function ); |
577 | |
|
578 | 0 | goto on_error; |
579 | 0 | } |
580 | 46 | value_key->data = (uint8_t *) memory_allocate( |
581 | 46 | sizeof( uint8_t ) * value_key->data_size ); |
582 | | |
583 | 46 | if( value_key->data == NULL ) |
584 | 0 | { |
585 | 0 | libcerror_error_set( |
586 | 0 | error, |
587 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
588 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
589 | 0 | "%s: unable to create data.", |
590 | 0 | function ); |
591 | |
|
592 | 0 | goto on_error; |
593 | 0 | } |
594 | 46 | value_key->data_size = (size_t) value_key->data_size; |
595 | | |
596 | 46 | if( memory_copy( |
597 | 46 | value_key->data, |
598 | 46 | &( ( ( (regf_value_key_t *) &( data[ data_offset ] ) )->data_offset )[ 4 - value_key->data_size ] ), |
599 | 46 | value_key->data_size ) == NULL ) |
600 | 0 | { |
601 | 0 | libcerror_error_set( |
602 | 0 | error, |
603 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
604 | 0 | LIBCERROR_MEMORY_ERROR_COPY_FAILED, |
605 | 0 | "%s: unable to copy data.", |
606 | 0 | function ); |
607 | |
|
608 | 0 | goto on_error; |
609 | 0 | } |
610 | 46 | if( correct_string_size != 0 ) |
611 | 2 | { |
612 | | /* Make sure remnant data in the string is zero-ed out |
613 | | */ |
614 | 2 | value_key->data[ value_key->data_size - 1 ] = 0; |
615 | 2 | } |
616 | 46 | } |
617 | 48 | } |
618 | 251 | data_offset += sizeof( regf_value_key_t ); |
619 | | |
620 | 251 | if( value_key->name_size > 0 ) |
621 | 176 | { |
622 | | /* TODO mark value as corrupted and handle issue */ |
623 | 176 | if( value_key->name_size > ( data_size - data_offset ) ) |
624 | 33 | { |
625 | 33 | libcerror_error_set( |
626 | 33 | error, |
627 | 33 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
628 | 33 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
629 | 33 | "%s: invalid value name size value out of bounds.", |
630 | 33 | function ); |
631 | | |
632 | 33 | goto on_error; |
633 | 33 | } |
634 | 143 | value_key->name = (uint8_t *) memory_allocate( |
635 | 143 | sizeof( uint8_t ) * (size_t) value_key->name_size ); |
636 | | |
637 | 143 | if( value_key->name == NULL ) |
638 | 0 | { |
639 | 0 | libcerror_error_set( |
640 | 0 | error, |
641 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
642 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
643 | 0 | "%s: unable to create value name.", |
644 | 0 | function ); |
645 | |
|
646 | 0 | goto on_error; |
647 | 0 | } |
648 | 143 | if( memory_copy( |
649 | 143 | value_key->name, |
650 | 143 | &( data[ data_offset ] ), |
651 | 143 | (size_t) value_key->name_size ) == NULL ) |
652 | 0 | { |
653 | 0 | libcerror_error_set( |
654 | 0 | error, |
655 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
656 | 0 | LIBCERROR_MEMORY_ERROR_COPY_FAILED, |
657 | 0 | "%s: unable to copy value name.", |
658 | 0 | function ); |
659 | |
|
660 | 0 | goto on_error; |
661 | 0 | } |
662 | 143 | value_key->name_hash = 0; |
663 | | |
664 | 2.77k | while( name_index < (size_t) value_key->name_size ) |
665 | 2.64k | { |
666 | 2.64k | if( ( value_key->flags & LIBREGF_VALUE_KEY_FLAG_NAME_IS_ASCII ) != 0 ) |
667 | 2.15k | { |
668 | 2.15k | result = libuna_unicode_character_copy_from_byte_stream( |
669 | 2.15k | &unicode_character, |
670 | 2.15k | value_key->name, |
671 | 2.15k | (size_t) value_key->name_size, |
672 | 2.15k | &name_index, |
673 | 2.15k | io_handle->ascii_codepage, |
674 | 2.15k | error ); |
675 | 2.15k | } |
676 | 492 | else |
677 | 492 | { |
678 | 492 | result = libuna_unicode_character_copy_from_utf16_stream( |
679 | 492 | &unicode_character, |
680 | 492 | value_key->name, |
681 | 492 | (size_t) value_key->name_size, |
682 | 492 | &name_index, |
683 | 492 | LIBUNA_ENDIAN_LITTLE, |
684 | 492 | error ); |
685 | 492 | } |
686 | 2.64k | if( result != 1 ) |
687 | 11 | { |
688 | 11 | libcerror_error_set( |
689 | 11 | error, |
690 | 11 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
691 | 11 | LIBCERROR_RUNTIME_ERROR_COPY_FAILED, |
692 | 11 | "%s: unable to copy value name to Unicode character.", |
693 | 11 | function ); |
694 | | |
695 | 11 | goto on_error; |
696 | 11 | } |
697 | 2.63k | value_key->name_hash *= 37; |
698 | 2.63k | value_key->name_hash += (uint32_t) towupper( (wint_t) unicode_character ); |
699 | 2.63k | } |
700 | | #if defined( HAVE_DEBUG_OUTPUT ) |
701 | | if( libcnotify_verbose != 0 ) |
702 | | { |
703 | | if( ( value_key->flags & LIBREGF_VALUE_KEY_FLAG_NAME_IS_ASCII ) != 0 ) |
704 | | { |
705 | | if( libregf_debug_print_string_value( |
706 | | function, |
707 | | "value name\t\t\t\t\t", |
708 | | value_key->name, |
709 | | (size_t) value_key->name_size, |
710 | | io_handle->ascii_codepage, |
711 | | error ) != 1 ) |
712 | | { |
713 | | libcerror_error_set( |
714 | | error, |
715 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
716 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
717 | | "%s: unable to print string value.", |
718 | | function ); |
719 | | |
720 | | goto on_error; |
721 | | } |
722 | | } |
723 | | else |
724 | | { |
725 | | if( libregf_debug_print_utf16_string_value( |
726 | | function, |
727 | | "value name\t\t\t\t\t", |
728 | | value_key->name, |
729 | | (size_t) value_key->name_size, |
730 | | LIBUNA_ENDIAN_LITTLE, |
731 | | error ) != 1 ) |
732 | | { |
733 | | libcerror_error_set( |
734 | | error, |
735 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
736 | | LIBCERROR_RUNTIME_ERROR_PRINT_FAILED, |
737 | | "%s: unable to print UTF-16 string value.", |
738 | | function ); |
739 | | |
740 | | goto on_error; |
741 | | } |
742 | | } |
743 | | if( result != 1 ) |
744 | | { |
745 | | libcerror_error_set( |
746 | | error, |
747 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
748 | | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
749 | | "%s: unable to retrieve value name string size.", |
750 | | function ); |
751 | | |
752 | | goto on_error; |
753 | | } |
754 | | libcnotify_printf( |
755 | | "%s: value name hash\t\t\t\t: 0x%08" PRIx32 "\n", |
756 | | function, |
757 | | value_key->name_hash ); |
758 | | } |
759 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
760 | 143 | } |
761 | | #if defined( HAVE_DEBUG_OUTPUT ) |
762 | | else if( libcnotify_verbose != 0 ) |
763 | | { |
764 | | libcnotify_printf( |
765 | | "%s: value name\t\t\t\t\t: (default)\n", |
766 | | function ); |
767 | | |
768 | | libcnotify_printf( |
769 | | "%s: value name hash\t\t\t\t: 0x%08" PRIx32 "\n", |
770 | | function, |
771 | | value_key->name_hash ); |
772 | | } |
773 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
774 | | |
775 | 207 | data_offset += value_key->name_size; |
776 | | |
777 | | #if defined( HAVE_DEBUG_OUTPUT ) |
778 | | if( libcnotify_verbose != 0 ) |
779 | | { |
780 | | if( ( value_key_hash != 0 ) |
781 | | && ( value_key_hash != value_key->name_hash ) ) |
782 | | { |
783 | | libcnotify_printf( |
784 | | "%s: mismatch in name hash ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n", |
785 | | function, |
786 | | value_key_hash, |
787 | | value_key->name_hash ); |
788 | | } |
789 | | if( data_offset < data_size ) |
790 | | { |
791 | | libcnotify_printf( |
792 | | "%s: padding:\n", |
793 | | function ); |
794 | | libcnotify_print_data( |
795 | | &( data[ data_offset ] ), |
796 | | data_size - data_offset, |
797 | | 0 ); |
798 | | } |
799 | | else |
800 | | { |
801 | | libcnotify_printf( |
802 | | "\n" ); |
803 | | } |
804 | | } |
805 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
806 | | |
807 | 207 | return( 1 ); |
808 | | |
809 | 91 | on_error: |
810 | 91 | if( value_key->data != NULL ) |
811 | 27 | { |
812 | 27 | memory_free( |
813 | 27 | value_key->data ); |
814 | | |
815 | 27 | value_key->data = NULL; |
816 | 27 | } |
817 | 91 | value_key->data_size = 0; |
818 | | |
819 | 91 | if( value_key->name != NULL ) |
820 | 11 | { |
821 | 11 | memory_free( |
822 | 11 | value_key->name ); |
823 | | |
824 | 11 | value_key->name = NULL; |
825 | 11 | } |
826 | 91 | value_key->name_size = 0; |
827 | | |
828 | 91 | return( -1 ); |
829 | 251 | } |
830 | | |
831 | | /* Retrieves the value name size |
832 | | * Returns 1 if successful or -1 on error |
833 | | */ |
834 | | int libregf_value_key_get_name_size( |
835 | | libregf_value_key_t *value_key, |
836 | | size_t *name_size, |
837 | | libcerror_error_t **error ) |
838 | 0 | { |
839 | 0 | static char *function = "libregf_value_key_get_name_size"; |
840 | |
|
841 | 0 | if( value_key == NULL ) |
842 | 0 | { |
843 | 0 | libcerror_error_set( |
844 | 0 | error, |
845 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
846 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
847 | 0 | "%s: invalid value key.", |
848 | 0 | function ); |
849 | |
|
850 | 0 | return( -1 ); |
851 | 0 | } |
852 | 0 | if( name_size == NULL ) |
853 | 0 | { |
854 | 0 | libcerror_error_set( |
855 | 0 | error, |
856 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
857 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
858 | 0 | "%s: invalid name size.", |
859 | 0 | function ); |
860 | |
|
861 | 0 | return( -1 ); |
862 | 0 | } |
863 | 0 | *name_size = value_key->name_size; |
864 | |
|
865 | 0 | return( 1 ); |
866 | 0 | } |
867 | | |
868 | | /* Retrieves the value name |
869 | | * Returns 1 if successful or -1 on error |
870 | | */ |
871 | | int libregf_value_key_get_name( |
872 | | libregf_value_key_t *value_key, |
873 | | uint8_t *name, |
874 | | size_t name_size, |
875 | | libcerror_error_t **error ) |
876 | 0 | { |
877 | 0 | static char *function = "libregf_value_key_get_name"; |
878 | |
|
879 | 0 | if( value_key == NULL ) |
880 | 0 | { |
881 | 0 | libcerror_error_set( |
882 | 0 | error, |
883 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
884 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
885 | 0 | "%s: invalid value key.", |
886 | 0 | function ); |
887 | |
|
888 | 0 | return( -1 ); |
889 | 0 | } |
890 | 0 | if( name == NULL ) |
891 | 0 | { |
892 | 0 | libcerror_error_set( |
893 | 0 | error, |
894 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
895 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
896 | 0 | "%s: invalid name.", |
897 | 0 | function ); |
898 | |
|
899 | 0 | return( -1 ); |
900 | 0 | } |
901 | 0 | if( name_size > (size_t) SSIZE_MAX ) |
902 | 0 | { |
903 | 0 | libcerror_error_set( |
904 | 0 | error, |
905 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
906 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, |
907 | 0 | "%s: invalid name size value exceeds maximum.", |
908 | 0 | function ); |
909 | |
|
910 | 0 | return( -1 ); |
911 | 0 | } |
912 | 0 | if( name_size < value_key->name_size ) |
913 | 0 | { |
914 | 0 | libcerror_error_set( |
915 | 0 | error, |
916 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
917 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, |
918 | 0 | "%s: invalid name size value out of bounds.", |
919 | 0 | function ); |
920 | |
|
921 | 0 | return( -1 ); |
922 | 0 | } |
923 | 0 | if( memory_copy( |
924 | 0 | name, |
925 | 0 | value_key->name, |
926 | 0 | value_key->name_size ) == NULL ) |
927 | 0 | { |
928 | 0 | libcerror_error_set( |
929 | 0 | error, |
930 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
931 | 0 | LIBCERROR_MEMORY_ERROR_COPY_FAILED, |
932 | 0 | "%s: unable to copy name.", |
933 | 0 | function ); |
934 | |
|
935 | 0 | return( -1 ); |
936 | 0 | } |
937 | 0 | return( 1 ); |
938 | 0 | } |
939 | | |
940 | | /* Retrieves the UTF-8 string size of the value name |
941 | | * The returned size includes the end of string character |
942 | | * Returns 1 if successful or -1 on error |
943 | | */ |
944 | | int libregf_value_key_get_utf8_name_size( |
945 | | libregf_value_key_t *value_key, |
946 | | size_t *utf8_name_size, |
947 | | int ascii_codepage, |
948 | | libcerror_error_t **error ) |
949 | 0 | { |
950 | 0 | static char *function = "libregf_value_key_get_utf8_name_size"; |
951 | 0 | int result = 0; |
952 | |
|
953 | 0 | if( value_key == NULL ) |
954 | 0 | { |
955 | 0 | libcerror_error_set( |
956 | 0 | error, |
957 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
958 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
959 | 0 | "%s: invalid value key.", |
960 | 0 | function ); |
961 | |
|
962 | 0 | return( -1 ); |
963 | 0 | } |
964 | 0 | if( value_key->name == NULL ) |
965 | 0 | { |
966 | 0 | if( utf8_name_size == NULL ) |
967 | 0 | { |
968 | 0 | libcerror_error_set( |
969 | 0 | error, |
970 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
971 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
972 | 0 | "%s: invalid UTF-8 name size.", |
973 | 0 | function ); |
974 | |
|
975 | 0 | return( -1 ); |
976 | 0 | } |
977 | 0 | *utf8_name_size = 0; |
978 | 0 | } |
979 | 0 | else |
980 | 0 | { |
981 | 0 | if( ( value_key->flags & LIBREGF_VALUE_KEY_FLAG_NAME_IS_ASCII ) != 0 ) |
982 | 0 | { |
983 | 0 | result = libuna_utf8_string_size_from_byte_stream( |
984 | 0 | value_key->name, |
985 | 0 | (size_t) value_key->name_size, |
986 | 0 | ascii_codepage, |
987 | 0 | utf8_name_size, |
988 | 0 | error ); |
989 | 0 | } |
990 | 0 | else |
991 | 0 | { |
992 | 0 | result = libuna_utf8_string_size_from_utf16_stream( |
993 | 0 | value_key->name, |
994 | 0 | (size_t) value_key->name_size, |
995 | 0 | LIBUNA_ENDIAN_LITTLE, |
996 | 0 | utf8_name_size, |
997 | 0 | error ); |
998 | 0 | } |
999 | 0 | if( result != 1 ) |
1000 | 0 | { |
1001 | 0 | libcerror_error_set( |
1002 | 0 | error, |
1003 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1004 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1005 | 0 | "%s: unable to retrieve UTF-8 string size.", |
1006 | 0 | function ); |
1007 | |
|
1008 | 0 | return( -1 ); |
1009 | 0 | } |
1010 | 0 | } |
1011 | 0 | return( 1 ); |
1012 | 0 | } |
1013 | | |
1014 | | /* Retrieves the UTF-8 string value of the value name |
1015 | | * The function uses a codepage if necessary, it uses the codepage set for the library |
1016 | | * The size should include the end of string character |
1017 | | * Returns 1 if successful or -1 on error |
1018 | | */ |
1019 | | int libregf_value_key_get_utf8_name( |
1020 | | libregf_value_key_t *value_key, |
1021 | | uint8_t *utf8_name, |
1022 | | size_t utf8_name_size, |
1023 | | int ascii_codepage, |
1024 | | libcerror_error_t **error ) |
1025 | 0 | { |
1026 | 0 | static char *function = "libregf_value_key_get_utf8_name"; |
1027 | 0 | int result = 0; |
1028 | |
|
1029 | 0 | if( value_key == NULL ) |
1030 | 0 | { |
1031 | 0 | libcerror_error_set( |
1032 | 0 | error, |
1033 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1034 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1035 | 0 | "%s: invalid value key.", |
1036 | 0 | function ); |
1037 | |
|
1038 | 0 | return( -1 ); |
1039 | 0 | } |
1040 | 0 | if( value_key->name == NULL ) |
1041 | 0 | { |
1042 | 0 | libcerror_error_set( |
1043 | 0 | error, |
1044 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1045 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
1046 | 0 | "%s: invalid value key - missing name.", |
1047 | 0 | function ); |
1048 | |
|
1049 | 0 | return( -1 ); |
1050 | 0 | } |
1051 | 0 | if( ( value_key->flags & LIBREGF_VALUE_KEY_FLAG_NAME_IS_ASCII ) != 0 ) |
1052 | 0 | { |
1053 | 0 | result = libuna_utf8_string_copy_from_byte_stream( |
1054 | 0 | utf8_name, |
1055 | 0 | utf8_name_size, |
1056 | 0 | value_key->name, |
1057 | 0 | (size_t) value_key->name_size, |
1058 | 0 | ascii_codepage, |
1059 | 0 | error ); |
1060 | 0 | } |
1061 | 0 | else |
1062 | 0 | { |
1063 | 0 | result = libuna_utf8_string_copy_from_utf16_stream( |
1064 | 0 | utf8_name, |
1065 | 0 | utf8_name_size, |
1066 | 0 | value_key->name, |
1067 | 0 | (size_t) value_key->name_size, |
1068 | 0 | LIBUNA_ENDIAN_LITTLE, |
1069 | 0 | error ); |
1070 | 0 | } |
1071 | 0 | if( result != 1 ) |
1072 | 0 | { |
1073 | 0 | libcerror_error_set( |
1074 | 0 | error, |
1075 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1076 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1077 | 0 | "%s: unable to retrieve UTF-8 string.", |
1078 | 0 | function ); |
1079 | |
|
1080 | 0 | return( -1 ); |
1081 | 0 | } |
1082 | 0 | return( 1 ); |
1083 | 0 | } |
1084 | | |
1085 | | /* Retrieves the UTF-16 string size of the value name |
1086 | | * The returned size includes the end of string character |
1087 | | * Returns 1 if successful or -1 on error |
1088 | | */ |
1089 | | int libregf_value_key_get_utf16_name_size( |
1090 | | libregf_value_key_t *value_key, |
1091 | | size_t *utf16_name_size, |
1092 | | int ascii_codepage, |
1093 | | libcerror_error_t **error ) |
1094 | 0 | { |
1095 | 0 | static char *function = "libregf_value_key_get_utf16_name_size"; |
1096 | 0 | int result = 0; |
1097 | |
|
1098 | 0 | if( value_key == NULL ) |
1099 | 0 | { |
1100 | 0 | libcerror_error_set( |
1101 | 0 | error, |
1102 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1103 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1104 | 0 | "%s: invalid value key.", |
1105 | 0 | function ); |
1106 | |
|
1107 | 0 | return( -1 ); |
1108 | 0 | } |
1109 | 0 | if( value_key->name == NULL ) |
1110 | 0 | { |
1111 | 0 | if( utf16_name_size == NULL ) |
1112 | 0 | { |
1113 | 0 | libcerror_error_set( |
1114 | 0 | error, |
1115 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1116 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1117 | 0 | "%s: invalid UTF-16 name size.", |
1118 | 0 | function ); |
1119 | |
|
1120 | 0 | return( -1 ); |
1121 | 0 | } |
1122 | 0 | *utf16_name_size = 0; |
1123 | 0 | } |
1124 | 0 | else |
1125 | 0 | { |
1126 | 0 | if( ( value_key->flags & LIBREGF_VALUE_KEY_FLAG_NAME_IS_ASCII ) != 0 ) |
1127 | 0 | { |
1128 | 0 | result = libuna_utf16_string_size_from_byte_stream( |
1129 | 0 | value_key->name, |
1130 | 0 | (size_t) value_key->name_size, |
1131 | 0 | ascii_codepage, |
1132 | 0 | utf16_name_size, |
1133 | 0 | error ); |
1134 | 0 | } |
1135 | 0 | else |
1136 | 0 | { |
1137 | 0 | result = libuna_utf16_string_size_from_utf16_stream( |
1138 | 0 | value_key->name, |
1139 | 0 | (size_t) value_key->name_size, |
1140 | 0 | LIBUNA_ENDIAN_LITTLE, |
1141 | 0 | utf16_name_size, |
1142 | 0 | error ); |
1143 | 0 | } |
1144 | 0 | if( result != 1 ) |
1145 | 0 | { |
1146 | 0 | libcerror_error_set( |
1147 | 0 | error, |
1148 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1149 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1150 | 0 | "%s: unable to retrieve UTF-16 string size.", |
1151 | 0 | function ); |
1152 | |
|
1153 | 0 | return( -1 ); |
1154 | 0 | } |
1155 | 0 | } |
1156 | 0 | return( 1 ); |
1157 | 0 | } |
1158 | | |
1159 | | /* Retrieves the UTF-16 string value of the value name |
1160 | | * The function uses a codepage if necessary, it uses the codepage set for the library |
1161 | | * The size should include the end of string character |
1162 | | * Returns 1 if successful or -1 on error |
1163 | | */ |
1164 | | int libregf_value_key_get_utf16_name( |
1165 | | libregf_value_key_t *value_key, |
1166 | | uint16_t *utf16_name, |
1167 | | size_t utf16_name_size, |
1168 | | int ascii_codepage, |
1169 | | libcerror_error_t **error ) |
1170 | 0 | { |
1171 | 0 | static char *function = "libregf_value_key_get_utf16_name"; |
1172 | 0 | int result = 0; |
1173 | |
|
1174 | 0 | if( value_key == NULL ) |
1175 | 0 | { |
1176 | 0 | libcerror_error_set( |
1177 | 0 | error, |
1178 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1179 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1180 | 0 | "%s: invalid value key.", |
1181 | 0 | function ); |
1182 | |
|
1183 | 0 | return( -1 ); |
1184 | 0 | } |
1185 | 0 | if( value_key->name == NULL ) |
1186 | 0 | { |
1187 | 0 | libcerror_error_set( |
1188 | 0 | error, |
1189 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1190 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
1191 | 0 | "%s: invalid value key - missing name.", |
1192 | 0 | function ); |
1193 | |
|
1194 | 0 | return( -1 ); |
1195 | 0 | } |
1196 | 0 | if( ( value_key->flags & LIBREGF_VALUE_KEY_FLAG_NAME_IS_ASCII ) != 0 ) |
1197 | 0 | { |
1198 | 0 | result = libuna_utf16_string_copy_from_byte_stream( |
1199 | 0 | utf16_name, |
1200 | 0 | utf16_name_size, |
1201 | 0 | value_key->name, |
1202 | 0 | (size_t) value_key->name_size, |
1203 | 0 | ascii_codepage, |
1204 | 0 | error ); |
1205 | 0 | } |
1206 | 0 | else |
1207 | 0 | { |
1208 | 0 | result = libuna_utf16_string_copy_from_utf16_stream( |
1209 | 0 | utf16_name, |
1210 | 0 | utf16_name_size, |
1211 | 0 | value_key->name, |
1212 | 0 | (size_t) value_key->name_size, |
1213 | 0 | LIBUNA_ENDIAN_LITTLE, |
1214 | 0 | error ); |
1215 | 0 | } |
1216 | 0 | if( result != 1 ) |
1217 | 0 | { |
1218 | 0 | libcerror_error_set( |
1219 | 0 | error, |
1220 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1221 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1222 | 0 | "%s: unable to retrieve UTF-16 string.", |
1223 | 0 | function ); |
1224 | |
|
1225 | 0 | return( -1 ); |
1226 | 0 | } |
1227 | 0 | return( 1 ); |
1228 | 0 | } |
1229 | | |
1230 | | /* Retrieves the value type |
1231 | | * Returns 1 if successful or -1 on error |
1232 | | */ |
1233 | | int libregf_value_key_get_value_type( |
1234 | | libregf_value_key_t *value_key, |
1235 | | uint32_t *value_type, |
1236 | | libcerror_error_t **error ) |
1237 | 397 | { |
1238 | 397 | static char *function = "libregf_value_key_get_value_type"; |
1239 | | |
1240 | 397 | if( value_key == NULL ) |
1241 | 2 | { |
1242 | 2 | libcerror_error_set( |
1243 | 2 | error, |
1244 | 2 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1245 | 2 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1246 | 2 | "%s: invalid value key.", |
1247 | 2 | function ); |
1248 | | |
1249 | 2 | return( -1 ); |
1250 | 2 | } |
1251 | 395 | if( value_type == NULL ) |
1252 | 0 | { |
1253 | 0 | libcerror_error_set( |
1254 | 0 | error, |
1255 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1256 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1257 | 0 | "%s: invalid data type.", |
1258 | 0 | function ); |
1259 | |
|
1260 | 0 | return( -1 ); |
1261 | 0 | } |
1262 | 395 | *value_type = value_key->value_type; |
1263 | | |
1264 | 395 | return( 1 ); |
1265 | 395 | } |
1266 | | |
1267 | | /* Compares the value name with UTF-8 string |
1268 | | * Returns 1 if the names match, 0 if not or -1 on error |
1269 | | */ |
1270 | | int libregf_value_key_compare_name_with_utf8_string( |
1271 | | libregf_value_key_t *value_key, |
1272 | | uint32_t name_hash, |
1273 | | const uint8_t *utf8_string, |
1274 | | size_t utf8_string_length, |
1275 | | int ascii_codepage, |
1276 | | libcerror_error_t **error ) |
1277 | 0 | { |
1278 | 0 | static char *function = "libregf_value_key_compare_name_with_utf8_string"; |
1279 | 0 | libuna_unicode_character_t name_character = 0; |
1280 | 0 | libuna_unicode_character_t string_character = 0; |
1281 | 0 | size_t name_index = 0; |
1282 | 0 | size_t utf8_string_index = 0; |
1283 | 0 | int result = 0; |
1284 | |
|
1285 | 0 | if( value_key == NULL ) |
1286 | 0 | { |
1287 | 0 | libcerror_error_set( |
1288 | 0 | error, |
1289 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1290 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1291 | 0 | "%s: invalid value key.", |
1292 | 0 | function ); |
1293 | |
|
1294 | 0 | return( -1 ); |
1295 | 0 | } |
1296 | 0 | if( utf8_string_length > (size_t) SSIZE_MAX ) |
1297 | 0 | { |
1298 | 0 | libcerror_error_set( |
1299 | 0 | error, |
1300 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1301 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, |
1302 | 0 | "%s: invalid UTF-8 string length value exceeds maximum.", |
1303 | 0 | function ); |
1304 | |
|
1305 | 0 | return( -1 ); |
1306 | 0 | } |
1307 | | /* Check if we are looking for the nameless default value |
1308 | | */ |
1309 | 0 | if( value_key->name == NULL ) |
1310 | 0 | { |
1311 | 0 | if( ( utf8_string == NULL ) |
1312 | 0 | && ( utf8_string_length == 0 ) ) |
1313 | 0 | { |
1314 | 0 | return( 1 ); |
1315 | 0 | } |
1316 | 0 | } |
1317 | 0 | else if( ( name_hash == 0 ) |
1318 | 0 | || ( value_key->name_hash == 0 ) |
1319 | 0 | || ( value_key->name_hash == name_hash ) ) |
1320 | 0 | { |
1321 | | /* Do a full compare if there no name hash was provided or the name hash matches |
1322 | | */ |
1323 | 0 | while( name_index < (size_t) value_key->name_size ) |
1324 | 0 | { |
1325 | 0 | if( utf8_string_index >= utf8_string_length ) |
1326 | 0 | { |
1327 | 0 | break; |
1328 | 0 | } |
1329 | 0 | if( ( value_key->flags & LIBREGF_VALUE_KEY_FLAG_NAME_IS_ASCII ) != 0 ) |
1330 | 0 | { |
1331 | 0 | result = libuna_unicode_character_copy_from_byte_stream( |
1332 | 0 | &name_character, |
1333 | 0 | value_key->name, |
1334 | 0 | (size_t) value_key->name_size, |
1335 | 0 | &name_index, |
1336 | 0 | ascii_codepage, |
1337 | 0 | error ); |
1338 | 0 | } |
1339 | 0 | else |
1340 | 0 | { |
1341 | 0 | result = libuna_unicode_character_copy_from_utf16_stream( |
1342 | 0 | &name_character, |
1343 | 0 | value_key->name, |
1344 | 0 | (size_t) value_key->name_size, |
1345 | 0 | &name_index, |
1346 | 0 | LIBUNA_ENDIAN_LITTLE, |
1347 | 0 | error ); |
1348 | 0 | } |
1349 | 0 | if( result != 1 ) |
1350 | 0 | { |
1351 | 0 | libcerror_error_set( |
1352 | 0 | error, |
1353 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1354 | 0 | LIBCERROR_RUNTIME_ERROR_COPY_FAILED, |
1355 | 0 | "%s: unable to copy value name to Unicode character.", |
1356 | 0 | function ); |
1357 | |
|
1358 | 0 | return( -1 ); |
1359 | 0 | } |
1360 | 0 | if( libuna_unicode_character_copy_from_utf8( |
1361 | 0 | &string_character, |
1362 | 0 | utf8_string, |
1363 | 0 | utf8_string_length, |
1364 | 0 | &utf8_string_index, |
1365 | 0 | error ) != 1 ) |
1366 | 0 | { |
1367 | 0 | libcerror_error_set( |
1368 | 0 | error, |
1369 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1370 | 0 | LIBCERROR_RUNTIME_ERROR_COPY_FAILED, |
1371 | 0 | "%s: unable to copy UTF-8 string to Unicode character.", |
1372 | 0 | function ); |
1373 | |
|
1374 | 0 | return( -1 ); |
1375 | 0 | } |
1376 | 0 | if( towupper( (wint_t) name_character ) != towupper( (wint_t) string_character ) ) |
1377 | 0 | { |
1378 | 0 | break; |
1379 | 0 | } |
1380 | 0 | } |
1381 | 0 | if( ( name_index == (size_t) value_key->name_size ) |
1382 | 0 | && ( utf8_string_index == utf8_string_length ) ) |
1383 | 0 | { |
1384 | 0 | return( 1 ); |
1385 | 0 | } |
1386 | 0 | } |
1387 | 0 | return( 0 ); |
1388 | 0 | } |
1389 | | |
1390 | | /* Compares the value name with UTF-16 string |
1391 | | * Returns 1 if the names match, 0 if not or -1 on error |
1392 | | */ |
1393 | | int libregf_value_key_compare_name_with_utf16_string( |
1394 | | libregf_value_key_t *value_key, |
1395 | | uint32_t name_hash, |
1396 | | const uint16_t *utf16_string, |
1397 | | size_t utf16_string_length, |
1398 | | int ascii_codepage, |
1399 | | libcerror_error_t **error ) |
1400 | 0 | { |
1401 | 0 | static char *function = "libregf_value_key_compare_name_with_utf16_string"; |
1402 | 0 | libuna_unicode_character_t name_character = 0; |
1403 | 0 | libuna_unicode_character_t string_character = 0; |
1404 | 0 | size_t name_index = 0; |
1405 | 0 | size_t utf16_string_index = 0; |
1406 | 0 | int result = 0; |
1407 | |
|
1408 | 0 | if( value_key == NULL ) |
1409 | 0 | { |
1410 | 0 | libcerror_error_set( |
1411 | 0 | error, |
1412 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1413 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1414 | 0 | "%s: invalid value key.", |
1415 | 0 | function ); |
1416 | |
|
1417 | 0 | return( -1 ); |
1418 | 0 | } |
1419 | 0 | if( utf16_string_length > (size_t) SSIZE_MAX ) |
1420 | 0 | { |
1421 | 0 | libcerror_error_set( |
1422 | 0 | error, |
1423 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1424 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, |
1425 | 0 | "%s: invalid UTF-16 string length value exceeds maximum.", |
1426 | 0 | function ); |
1427 | |
|
1428 | 0 | return( -1 ); |
1429 | 0 | } |
1430 | | /* Check if we are looking for the nameless default value |
1431 | | */ |
1432 | 0 | if( value_key->name == NULL ) |
1433 | 0 | { |
1434 | 0 | if( ( utf16_string == NULL ) |
1435 | 0 | && ( utf16_string_length == 0 ) ) |
1436 | 0 | { |
1437 | 0 | return( 1 ); |
1438 | 0 | } |
1439 | 0 | } |
1440 | 0 | else if( ( name_hash == 0 ) |
1441 | 0 | || ( value_key->name_hash == 0 ) |
1442 | 0 | || ( value_key->name_hash == name_hash ) ) |
1443 | 0 | { |
1444 | | /* Do a full compare if there no name hash was provided or the name hash matches |
1445 | | */ |
1446 | 0 | while( name_index < (size_t) value_key->name_size ) |
1447 | 0 | { |
1448 | 0 | if( utf16_string_index >= utf16_string_length ) |
1449 | 0 | { |
1450 | 0 | break; |
1451 | 0 | } |
1452 | 0 | if( ( value_key->flags & LIBREGF_VALUE_KEY_FLAG_NAME_IS_ASCII ) != 0 ) |
1453 | 0 | { |
1454 | 0 | result = libuna_unicode_character_copy_from_byte_stream( |
1455 | 0 | &name_character, |
1456 | 0 | value_key->name, |
1457 | 0 | (size_t) value_key->name_size, |
1458 | 0 | &name_index, |
1459 | 0 | ascii_codepage, |
1460 | 0 | error ); |
1461 | 0 | } |
1462 | 0 | else |
1463 | 0 | { |
1464 | 0 | result = libuna_unicode_character_copy_from_utf16_stream( |
1465 | 0 | &name_character, |
1466 | 0 | value_key->name, |
1467 | 0 | (size_t) value_key->name_size, |
1468 | 0 | &name_index, |
1469 | 0 | LIBUNA_ENDIAN_LITTLE, |
1470 | 0 | error ); |
1471 | 0 | } |
1472 | 0 | if( result != 1 ) |
1473 | 0 | { |
1474 | 0 | libcerror_error_set( |
1475 | 0 | error, |
1476 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1477 | 0 | LIBCERROR_RUNTIME_ERROR_COPY_FAILED, |
1478 | 0 | "%s: unable to copy value name to Unicode character.", |
1479 | 0 | function ); |
1480 | |
|
1481 | 0 | return( -1 ); |
1482 | 0 | } |
1483 | 0 | if( libuna_unicode_character_copy_from_utf16( |
1484 | 0 | &string_character, |
1485 | 0 | utf16_string, |
1486 | 0 | utf16_string_length, |
1487 | 0 | &utf16_string_index, |
1488 | 0 | error ) != 1 ) |
1489 | 0 | { |
1490 | 0 | libcerror_error_set( |
1491 | 0 | error, |
1492 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1493 | 0 | LIBCERROR_RUNTIME_ERROR_COPY_FAILED, |
1494 | 0 | "%s: unable to copy UTF-16 string to Unicode character.", |
1495 | 0 | function ); |
1496 | |
|
1497 | 0 | return( -1 ); |
1498 | 0 | } |
1499 | 0 | if( towupper( (wint_t) name_character ) != towupper( (wint_t) string_character ) ) |
1500 | 0 | { |
1501 | 0 | break; |
1502 | 0 | } |
1503 | 0 | } |
1504 | 0 | if( ( name_index == (size_t) value_key->name_size ) |
1505 | 0 | && ( utf16_string_index == utf16_string_length ) ) |
1506 | 0 | { |
1507 | 0 | return( 1 ); |
1508 | 0 | } |
1509 | 0 | } |
1510 | 0 | return( 0 ); |
1511 | 0 | } |
1512 | | |