1 /*
2 * String values functions
3 *
4 * Copyright (C) 2011-2019, 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 <memory.h>
24 #include <types.h>
25
26 #include "libwrc_data_descriptor.h"
27 #include "libwrc_definitions.h"
28 #include "libwrc_io_handle.h"
29 #include "libwrc_language_entry.h"
30 #include "libwrc_libbfio.h"
31 #include "libwrc_libcerror.h"
32 #include "libwrc_libcnotify.h"
33 #include "libwrc_libfvalue.h"
34 #include "libwrc_string_values.h"
35
36 /* Reads string values
37 * Returns 1 if successful or -1 on error
38 */
libwrc_string_values_read(libwrc_language_entry_t * language_entry,libwrc_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,uint32_t identifier,libwrc_data_descriptor_t * data_descriptor,libcerror_error_t ** error)39 int libwrc_string_values_read(
40 libwrc_language_entry_t *language_entry,
41 libwrc_io_handle_t *io_handle,
42 libbfio_handle_t *file_io_handle,
43 uint32_t identifier,
44 libwrc_data_descriptor_t *data_descriptor,
45 libcerror_error_t **error )
46 {
47 libfvalue_value_t *string_value = NULL;
48 uint8_t *resource_data = NULL;
49 uint8_t *string_resource_data = NULL;
50 static char *function = "libwrc_string_values_read";
51 off64_t file_offset = 0;
52 size_t resource_data_size = 0;
53 ssize_t read_count = 0;
54 uint32_t string_identifier = 0;
55 uint32_t string_index = 0;
56 uint32_t string_size = 0;
57 int value_index = 0;
58
59 if( language_entry == NULL )
60 {
61 libcerror_error_set(
62 error,
63 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
64 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
65 "%s: invalid language entry.",
66 function );
67
68 return( -1 );
69 }
70 if( io_handle == NULL )
71 {
72 libcerror_error_set(
73 error,
74 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
75 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
76 "%s: invalid IO handle.",
77 function );
78
79 return( -1 );
80 }
81 if( data_descriptor == NULL )
82 {
83 libcerror_error_set(
84 error,
85 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
86 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
87 "%s: invalid data descriptor.",
88 function );
89
90 return( -1 );
91 }
92 file_offset = data_descriptor->virtual_address
93 - io_handle->virtual_address;
94
95 if( libbfio_handle_seek_offset(
96 file_io_handle,
97 file_offset,
98 SEEK_SET,
99 error ) == -1 )
100 {
101 libcerror_error_set(
102 error,
103 LIBCERROR_ERROR_DOMAIN_IO,
104 LIBCERROR_IO_ERROR_SEEK_FAILED,
105 "%s: unable to seek resource data offset: %" PRIi64 ".",
106 function,
107 file_offset );
108
109 goto on_error;
110 }
111 resource_data_size = (size_t) data_descriptor->size;
112
113 resource_data = (uint8_t *) memory_allocate(
114 sizeof( uint8_t ) * resource_data_size );
115
116 if( resource_data == NULL )
117 {
118 libcerror_error_set(
119 error,
120 LIBCERROR_ERROR_DOMAIN_MEMORY,
121 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
122 "%s: unable to create resource data.",
123 function );
124
125 goto on_error;
126 }
127 read_count = libbfio_handle_read_buffer(
128 file_io_handle,
129 resource_data,
130 resource_data_size,
131 error );
132
133 if( read_count != (ssize_t) resource_data_size )
134 {
135 libcerror_error_set(
136 error,
137 LIBCERROR_ERROR_DOMAIN_IO,
138 LIBCERROR_IO_ERROR_READ_FAILED,
139 "%s: unable to read resource data.",
140 function );
141
142 goto on_error;
143 }
144 string_resource_data = resource_data;
145
146 #if defined( HAVE_DEBUG_OUTPUT )
147 if( libcnotify_verbose != 0 )
148 {
149 libcnotify_printf(
150 "%s: resource data:\n",
151 function );
152 libcnotify_print_data(
153 string_resource_data,
154 resource_data_size,
155 0 );
156 }
157 #endif
158 while( resource_data_size > 0 )
159 {
160 byte_stream_copy_to_uint16_little_endian(
161 string_resource_data,
162 string_size );
163
164 string_resource_data += sizeof( uint16_t );
165 resource_data_size -= sizeof( uint16_t );
166
167 #if defined( HAVE_DEBUG_OUTPUT )
168 if( libcnotify_verbose != 0 )
169 {
170 libcnotify_printf(
171 "%s: string: %02" PRIu32 " length\t\t\t\t: %" PRIu32 "\n",
172 function,
173 string_index,
174 string_size );
175 }
176 #endif
177 if( string_size > 0 )
178 {
179 string_identifier = ( identifier << 4 ) | string_index;
180
181 string_size *= 2;
182
183 if( string_size > resource_data_size )
184 {
185 libcerror_error_set(
186 error,
187 LIBCERROR_ERROR_DOMAIN_RUNTIME,
188 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
189 "%s: string size value out of bound.",
190 function );
191
192 goto on_error;
193 }
194 if( libfvalue_value_type_initialize(
195 &string_value,
196 LIBFVALUE_VALUE_TYPE_STRING_UTF16,
197 error ) != 1 )
198 {
199 libcerror_error_set(
200 error,
201 LIBCERROR_ERROR_DOMAIN_RUNTIME,
202 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
203 "%s: unable to create string value.",
204 function );
205
206 goto on_error;
207 }
208 if( libfvalue_value_set_identifier(
209 string_value,
210 (uint8_t *) &string_identifier,
211 4,
212 LIBFVALUE_VALUE_IDENTIFIER_FLAG_MANAGED,
213 error ) != 1 )
214 {
215 libcerror_error_set(
216 error,
217 LIBCERROR_ERROR_DOMAIN_RUNTIME,
218 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
219 "%s: unable to set identifier of string value.",
220 function );
221
222 goto on_error;
223 }
224 #if defined( HAVE_DEBUG_OUTPUT )
225 if( libcnotify_verbose != 0 )
226 {
227 libcnotify_printf(
228 "%s: string: %02" PRIu32 " data:\n",
229 function,
230 string_index );
231 libcnotify_print_data(
232 string_resource_data,
233 (size_t) string_size,
234 0 );
235 }
236 #endif
237 if( libfvalue_value_set_data(
238 string_value,
239 string_resource_data,
240 (size_t) string_size,
241 LIBFVALUE_CODEPAGE_UTF16_LITTLE_ENDIAN,
242 LIBFVALUE_VALUE_DATA_FLAG_MANAGED,
243 error ) != 1 )
244 {
245 libcerror_error_set(
246 error,
247 LIBCERROR_ERROR_DOMAIN_RUNTIME,
248 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
249 "%s: unable to set data of string value.",
250 function );
251
252 goto on_error;
253 }
254 #if defined( HAVE_DEBUG_OUTPUT )
255 if( libcnotify_verbose != 0 )
256 {
257 libcnotify_printf(
258 "%s: string: %02" PRIu32 " value\t\t\t\t: ",
259 function,
260 string_index );
261
262 if( libfvalue_value_print(
263 string_value,
264 0,
265 0,
266 error ) != 1 )
267 {
268 libcerror_error_set(
269 error,
270 LIBCERROR_ERROR_DOMAIN_RUNTIME,
271 LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
272 "%s: unable to print string value.",
273 function );
274
275 goto on_error;
276 }
277 libcnotify_printf(
278 "\n" );
279 }
280 #endif
281 string_resource_data += (size_t) string_size;
282 resource_data_size -= (size_t) string_size;
283
284 if( libwrc_language_entry_append_value(
285 language_entry,
286 &value_index,
287 (intptr_t *) string_value,
288 error ) != 1 )
289 {
290 libcerror_error_set(
291 error,
292 LIBCERROR_ERROR_DOMAIN_RUNTIME,
293 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
294 "%s: unable to append string value.",
295 function );
296
297 goto on_error;
298 }
299 string_value = NULL;
300 }
301 #if defined( HAVE_DEBUG_OUTPUT )
302 else if( libcnotify_verbose != 0 )
303 {
304 libcnotify_printf(
305 "\n" );
306 }
307 #endif
308 string_index++;
309 }
310 memory_free(
311 resource_data );
312
313 /* TODO validate if number of strings is 16 ? */
314
315 return( 1 );
316
317 on_error:
318 if( string_value != NULL )
319 {
320 libfvalue_value_free(
321 &string_value,
322 NULL );
323 }
324 if( resource_data != NULL )
325 {
326 memory_free(
327 resource_data );
328 }
329 return( -1 );
330 }
331
332