1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** GUIX Component                                                        */
17 /**                                                                       */
18 /**   Binres Loader Management (Binres Loader)                            */
19 /**                                                                       */
20 /**************************************************************************/
21 
22 #define GX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "gx_api.h"
28 #include "gx_binres_loader.h"
29 #include "gx_system.h"
30 #include "gx_utility.h"
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _gx_binres_resource_header_load                     PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Kenneth Maxwell, Microsoft Corporation                              */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function reads resource header from a binary data buffer.      */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    info                                  Binary read control block     */
49 /*    header                                Returned resource header      */
50 /*                                                                        */
51 /*  OUTPUT                                                                */
52 /*                                                                        */
53 /*    Status                                Completion status             */
54 /*                                                                        */
55 /*  CALLS                                                                 */
56 /*                                                                        */
57 /*    None                                                                */
58 /*                                                                        */
59 /*  CALLED BY                                                             */
60 /*                                                                        */
61 /*    GUIX Internal Code                                                  */
62 /*                                                                        */
63 /*  RELEASE HISTORY                                                       */
64 /*                                                                        */
65 /*    DATE              NAME                      DESCRIPTION             */
66 /*                                                                        */
67 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
68 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
69 /*                                            removed use of memcpy,      */
70 /*                                            resulting in version 6.1    */
71 /*                                                                        */
72 /**************************************************************************/
73 #ifdef GX_BINARY_RESOURCE_SUPPORT
_gx_binres_resource_header_load(GX_BINRES_DATA_INFO * info,GX_RESOURCE_HEADER * header)74 UINT _gx_binres_resource_header_load(GX_BINRES_DATA_INFO *info, GX_RESOURCE_HEADER *header)
75 {
76     GX_BINRES_READ_USHORT(header -> gx_resource_header_magic_number, info -> gx_binres_root_address + info -> gx_binres_read_offset);
77     info -> gx_binres_read_offset += sizeof(USHORT);
78 
79     GX_BINRES_READ_USHORT(header -> gx_resource_header_version, info -> gx_binres_root_address + info -> gx_binres_read_offset);
80     info -> gx_binres_read_offset += sizeof(USHORT);
81 
82     GX_BINRES_READ_USHORT(header -> gx_resource_header_theme_count, info -> gx_binres_root_address + info -> gx_binres_read_offset);
83     info -> gx_binres_read_offset += sizeof(USHORT);
84 
85     GX_BINRES_READ_USHORT(header -> gx_resource_header_language_count, info -> gx_binres_root_address + info -> gx_binres_read_offset);
86     info -> gx_binres_read_offset += sizeof(USHORT);
87 
88     GX_BINRES_READ_ULONG(header -> gx_resource_header_theme_data_size, info -> gx_binres_root_address + info -> gx_binres_read_offset);
89     info -> gx_binres_read_offset += sizeof(ULONG);
90 
91     GX_BINRES_READ_ULONG(header -> gx_resource_header_string_data_size, info -> gx_binres_root_address + info -> gx_binres_read_offset);
92     info -> gx_binres_read_offset += sizeof(ULONG);
93 
94     GX_BINRES_READ_ULONG(header -> gx_resource_header_data_size, info -> gx_binres_root_address + info -> gx_binres_read_offset);
95     info -> gx_binres_read_offset += sizeof(ULONG);
96 
97     return GX_SUCCESS;
98 }
99 #endif
100 
101 /**************************************************************************/
102 /*                                                                        */
103 /*  FUNCTION                                               RELEASE        */
104 /*                                                                        */
105 /*    _gx_binres_string_header_load                       PORTABLE C      */
106 /*                                                           6.1          */
107 /*  AUTHOR                                                                */
108 /*                                                                        */
109 /*    Kenneth Maxwell, Microsoft Corporation                              */
110 /*                                                                        */
111 /*  DESCRIPTION                                                           */
112 /*                                                                        */
113 /*    This function reads string header from a binary data buffer.        */
114 /*                                                                        */
115 /*  INPUT                                                                 */
116 /*                                                                        */
117 /*    info                                  Binary read control block     */
118 /*    header                                Returned string header        */
119 /*                                                                        */
120 /*  OUTPUT                                                                */
121 /*                                                                        */
122 /*    Status                                Completion status             */
123 /*                                                                        */
124 /*  CALLS                                                                 */
125 /*                                                                        */
126 /*    None                                                                */
127 /*                                                                        */
128 /*  CALLED BY                                                             */
129 /*                                                                        */
130 /*    GUIX Internal Code                                                  */
131 /*                                                                        */
132 /*  RELEASE HISTORY                                                       */
133 /*                                                                        */
134 /*    DATE              NAME                      DESCRIPTION             */
135 /*                                                                        */
136 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
137 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
138 /*                                            removed use of memcpy,      */
139 /*                                            resulting in version 6.1    */
140 /*                                                                        */
141 /**************************************************************************/
142 #ifdef GX_BINARY_RESOURCE_SUPPORT
_gx_binres_string_header_load(GX_BINRES_DATA_INFO * info,GX_STRING_HEADER * header)143 UINT _gx_binres_string_header_load(GX_BINRES_DATA_INFO *info, GX_STRING_HEADER *header)
144 {
145     GX_BINRES_READ_USHORT(header -> gx_string_header_magic_number, info -> gx_binres_root_address + info -> gx_binres_read_offset);
146     info -> gx_binres_read_offset += sizeof(USHORT);
147 
148     GX_BINRES_READ_USHORT(header -> gx_string_header_language_count, info -> gx_binres_root_address + info -> gx_binres_read_offset);
149     info -> gx_binres_read_offset += sizeof(USHORT);
150 
151     GX_BINRES_READ_USHORT(header -> gx_string_header_string_count, info -> gx_binres_root_address + info -> gx_binres_read_offset);
152     info -> gx_binres_read_offset += sizeof(USHORT);
153 
154     GX_BINRES_READ_ULONG(header -> gx_string_header_data_size, info -> gx_binres_root_address + info -> gx_binres_read_offset);
155     info -> gx_binres_read_offset += sizeof(ULONG);
156 
157     return GX_SUCCESS;
158 }
159 #endif
160 
161 /**************************************************************************/
162 /*                                                                        */
163 /*  FUNCTION                                               RELEASE        */
164 /*                                                                        */
165 /*    _gx_binres_language_header_load                     PORTABLE C      */
166 /*                                                           6.1          */
167 /*  AUTHOR                                                                */
168 /*                                                                        */
169 /*    Kenneth Maxwell, Microsoft Corporation                              */
170 /*                                                                        */
171 /*  DESCRIPTION                                                           */
172 /*                                                                        */
173 /*    This function reads language header from a binary data buffer.      */
174 /*                                                                        */
175 /*  INPUT                                                                 */
176 /*                                                                        */
177 /*    info                                  Binary read control block     */
178 /*    header                                Returned language header      */
179 /*                                                                        */
180 /*  OUTPUT                                                                */
181 /*                                                                        */
182 /*    Status                                Completion status             */
183 /*                                                                        */
184 /*  CALLS                                                                 */
185 /*                                                                        */
186 /*    None                                                                */
187 /*                                                                        */
188 /*  CALLED BY                                                             */
189 /*                                                                        */
190 /*    GUIX Internal Code                                                  */
191 /*                                                                        */
192 /*  RELEASE HISTORY                                                       */
193 /*                                                                        */
194 /*    DATE              NAME                      DESCRIPTION             */
195 /*                                                                        */
196 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
197 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
198 /*                                            removed use of memcpy,      */
199 /*                                            resulting in version 6.1    */
200 /*                                                                        */
201 /**************************************************************************/
202 #ifdef GX_BINARY_RESOURCE_SUPPORT
_gx_binres_language_header_load(GX_BINRES_DATA_INFO * info,GX_LANGUAGE_HEADER * header)203 UINT _gx_binres_language_header_load(GX_BINRES_DATA_INFO *info, GX_LANGUAGE_HEADER *header)
204 {
205     GX_BINRES_READ_USHORT(header -> gx_language_header_magic_number, info -> gx_binres_root_address + info -> gx_binres_read_offset);
206     info -> gx_binres_read_offset += sizeof(USHORT);
207 
208     GX_BINRES_READ_USHORT(header -> gx_language_header_index, info -> gx_binres_root_address + info -> gx_binres_read_offset);
209     info -> gx_binres_read_offset += sizeof(USHORT);
210 
211     memcpy(&header->gx_language_header_name, info->gx_binres_root_address + info->gx_binres_read_offset, sizeof(header->gx_language_header_name)); /* Use case of memcpy is verified. */
212     info -> gx_binres_read_offset += sizeof(header -> gx_language_header_name);
213 
214     GX_BINRES_READ_ULONG(header -> gx_language_header_data_size, info -> gx_binres_root_address + info -> gx_binres_read_offset);
215     info -> gx_binres_read_offset += sizeof(ULONG);
216 
217     return GX_SUCCESS;
218 }
219 #endif
220 
221 /**************************************************************************/
222 /*                                                                        */
223 /*  FUNCTION                                               RELEASE        */
224 /*                                                                        */
225 /*    _gx_binres_language_table_buffer_allocate           PORTABLE C      */
226 /*                                                           6.1.7        */
227 /*  AUTHOR                                                                */
228 /*                                                                        */
229 /*    Kenneth Maxwell, Microsoft Corporation                              */
230 /*                                                                        */
231 /*  DESCRIPTION                                                           */
232 /*                                                                        */
233 /*    This function allocates needed memory buffer for loading language   */
234 /*    table.                                                              */
235 /*                                                                        */
236 /*  INPUT                                                                 */
237 /*                                                                        */
238 /*    info                                  Binary resource control block */
239 /*    language_table_type_size              Size of language table type   */
240 /*    string_table_type_size                Size of string table type     */
241 /*                                                                        */
242 /*  OUTPUT                                                                */
243 /*                                                                        */
244 /*    Status                                Completion status             */
245 /*                                                                        */
246 /*  CALLS                                                                 */
247 /*                                                                        */
248 /*    _gx_system_memory_allocator           Application defined memory    */
249 /*                                            allocation function         */
250 /*    _gx_binres_resource_header_load       Read binary resource header   */
251 /*    _gx_binres_string_header_load         Read string data header       */
252 /*                                                                        */
253 /*  CALLED BY                                                             */
254 /*                                                                        */
255 /*    GUIX Internal Code                                                  */
256 /*                                                                        */
257 /*  RELEASE HISTORY                                                       */
258 /*                                                                        */
259 /*    DATE              NAME                      DESCRIPTION             */
260 /*                                                                        */
261 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
262 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
263 /*                                            resulting in version 6.1    */
264 /*  06-02-2021     Kenneth Maxwell          Modified comment(s),          */
265 /*                                            test for langauge_count == 0*/
266 /*                                            resulting in version 6.1.7  */
267 /*                                                                        */
268 /**************************************************************************/
269 #ifdef GX_BINARY_RESOURCE_SUPPORT
_gx_binres_language_table_buffer_allocate(GX_BINRES_DATA_INFO * info,GX_UBYTE language_table_type_size,GX_UBYTE string_table_type_size)270 static UINT _gx_binres_language_table_buffer_allocate(GX_BINRES_DATA_INFO *info, GX_UBYTE language_table_type_size, GX_UBYTE string_table_type_size)
271 {
272 GX_RESOURCE_HEADER res_header;
273 GX_STRING_HEADER   string_header;
274 USHORT             language_count;
275 USHORT             string_count;
276 UINT               language_table_size;
277 UINT               string_table_size;
278 
279     info -> gx_binres_read_offset = 0;
280 
281     /* Read resource header.  */
282     _gx_binres_resource_header_load(info, &res_header);
283     info -> gx_binres_read_offset += res_header.gx_resource_header_theme_data_size;
284 
285     if (res_header.gx_resource_header_magic_number != GX_MAGIC_NUMBER)
286     {
287         return GX_INVALID_FORMAT;
288     }
289 
290     _gx_binres_string_header_load(info, &string_header);
291 
292     if (string_header.gx_string_header_magic_number != GX_MAGIC_NUMBER)
293     {
294         return GX_INVALID_FORMAT;
295     }
296 
297     language_count = string_header.gx_string_header_language_count;
298 
299     if (language_count == 0)
300     {
301         return GX_INVALID_FORMAT;
302     }
303     string_count = string_header.gx_string_header_string_count;
304 
305     /* Calcualte memory size needed for string tables. */
306     string_table_size = (UINT)(string_count * string_table_type_size);
307     GX_UTILITY_MATH_UINT_MULT(string_table_size, language_count, string_table_size)
308 
309     /* Calculate memory size needed for language table. */
310     language_table_size = (UINT)(language_table_type_size * language_count);
311 
312     /* Calculate memory size needed.  */
313     GX_UTILITY_MATH_UINT_ADD(string_table_size, language_table_size, info -> gx_binres_buffer_size)
314 
315     info -> gx_binres_buffer = (GX_UBYTE *)_gx_system_memory_allocator(info -> gx_binres_buffer_size);
316 
317     if (!info -> gx_binres_buffer)
318     {
319         return GX_SYSTEM_MEMORY_ERROR;
320     }
321 
322     memset(info -> gx_binres_buffer, 0, info -> gx_binres_buffer_size);
323     info -> gx_binres_buffer_index = 0;
324 
325     return GX_SUCCESS;
326 }
327 #endif
328 
329 /**************************************************************************/
330 /*                                                                        */
331 /*  FUNCTION                                               RELEASE        */
332 /*                                                                        */
333 /*    _gx_binres_language_table_load                      PORTABLE C      */
334 /*                                                           6.1          */
335 /*  AUTHOR                                                                */
336 /*                                                                        */
337 /*    Kenneth Maxwell, Microsoft Corporation                              */
338 /*                                                                        */
339 /*  DESCRIPTION (deprecated)                                              */
340 /*                                                                        */
341 /*    This service loads a language table from a binary data buffer.      */
342 /*                                                                        */
343 /*  INPUT                                                                 */
344 /*                                                                        */
345 /*    root_address                          Root address of binary        */
346 /*                                            resource data               */
347 /*    returned_language_table               Pointer to loaded language    */
348 /*                                           table                        */
349 /*                                                                        */
350 /*  OUTPUT                                                                */
351 /*                                                                        */
352 /*    Status                                Completion status             */
353 /*                                                                        */
354 /*  CALLS                                                                 */
355 /*                                                                        */
356 /*    _gx_binres_language_table_buffer_allocate                           */
357 /*                                          Allocate needed buffer for    */
358 /*                                            loading language table      */
359 /*    _gx_binres_resource_header_load                                     */
360 /*                                          Read resource header          */
361 /*    _gx_binres_string_header_load         Read string data header       */
362 /*    _gx_binres_language_header_load       Read language data header     */
363 /*    _gx_system_memory_free                Application defined memory    */
364 /*                                            free function               */
365 /*                                                                        */
366 /*  CALLED BY                                                             */
367 /*                                                                        */
368 /*    Application Code                                                    */
369 /*                                                                        */
370 /*  RELEASE HISTORY                                                       */
371 /*                                                                        */
372 /*    DATE              NAME                      DESCRIPTION             */
373 /*                                                                        */
374 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
375 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
376 /*                                            removed use of memcpy,      */
377 /*                                            resulting in version 6.1    */
378 /*                                                                        */
379 /**************************************************************************/
380 #ifdef GX_BINARY_RESOURCE_SUPPORT
381 #ifdef GX_ENABLE_DEPRECATED_STRING_API
_gx_binres_language_table_load(GX_UBYTE * root_address,GX_UBYTE **** returned_language_table)382 UINT _gx_binres_language_table_load(GX_UBYTE *root_address, GX_UBYTE ****returned_language_table)
383 {
384 UINT                status;
385 GX_BINRES_DATA_INFO info;
386 GX_RESOURCE_HEADER  header;
387 GX_STRING_HEADER    string_header;
388 GX_LANGUAGE_HEADER  language_header;
389 GX_UBYTE         ***language_table;
390 UINT                lang_index;
391 UINT                string_index;
392 USHORT              string_length;
393 GX_CHAR             get_char;
394 
395     memset(&info, 0, sizeof(GX_BINRES_DATA_INFO));
396 
397     info.gx_binres_root_address = root_address;
398 
399     /* Allocate memory that needed for language table.  */
400     status = _gx_binres_language_table_buffer_allocate(&info, sizeof(GX_UBYTE * *), sizeof(GX_UBYTE *));
401 
402     /* Read Resource header. */
403     info.gx_binres_read_offset = 0;
404     _gx_binres_resource_header_load(&info, &header);
405 
406     /* Skip theme info.  */
407     info.gx_binres_read_offset += header.gx_resource_header_theme_data_size;
408 
409     if (header.gx_resource_header_magic_number != GX_MAGIC_NUMBER)
410     {
411         return GX_INVALID_FORMAT;
412     }
413 
414     language_table = GX_NULL;
415 
416     /* Read language table.  */
417     if (status == GX_SUCCESS)
418     {
419         /* Read string header. */
420         _gx_binres_string_header_load(&info, &string_header);
421 
422         language_table = (GX_UBYTE ***)(info.gx_binres_buffer + info.gx_binres_buffer_index);
423         info.gx_binres_buffer_index += sizeof(GX_UBYTE * *) * string_header.gx_string_header_language_count;
424 
425         for (lang_index = 0; lang_index < string_header.gx_string_header_language_count; lang_index++)
426         {
427             /* Read language header.  */
428             _gx_binres_language_header_load(&info, &language_header);
429 
430             if (language_header.gx_language_header_magic_number != GX_MAGIC_NUMBER)
431             {
432                 status = GX_INVALID_FORMAT;
433                 break;
434             }
435 
436             /* Read string table.  */
437             language_table[lang_index] = (GX_UBYTE **)(info.gx_binres_buffer + info.gx_binres_buffer_index);
438             info.gx_binres_buffer_index += sizeof(GX_UBYTE *) * string_header.gx_string_header_string_count;
439 
440             if (header.gx_resource_header_version >= GX_BINRES_VERSION_ADD_STRING_LENGTH)
441             {
442                 for (string_index = 1; string_index < string_header.gx_string_header_string_count; string_index++)
443                 {
444                     /* Read string length. */
445                     GX_BINRES_READ_USHORT(string_length, info.gx_binres_root_address + info.gx_binres_read_offset);
446                     info.gx_binres_read_offset += sizeof(USHORT);
447 
448                     if (string_length == 0)
449                     {
450                         language_table[lang_index][string_index] = GX_NULL;
451                     }
452                     else
453                     {
454                         language_table[lang_index][string_index] = (GX_UBYTE *)(info.gx_binres_root_address + info.gx_binres_read_offset);
455                         info.gx_binres_read_offset += (UINT)(string_length + 1);
456                     }
457                 }
458             }
459             else
460             {
461                 string_index = 1;
462                 string_length = 0;
463                 while (string_index < string_header.gx_string_header_string_count)
464                 {
465                     string_length++;
466 
467                     get_char = (GX_CHAR)info.gx_binres_root_address[info.gx_binres_read_offset];
468                     info.gx_binres_read_offset++;
469 
470                     if (get_char == '\0')
471                     {
472                         if (string_length == 1)
473                         {
474                             language_table[lang_index][string_index] = GX_NULL;
475                         }
476                         else
477                         {
478                             language_table[lang_index][string_index] = (GX_UBYTE *)(info.gx_binres_root_address + info.gx_binres_read_offset - string_length);
479                         }
480 
481                         string_length = 0;
482                         string_index++;
483                     }
484                 }
485             }
486         }
487     }
488 
489     if (status == GX_SUCCESS)
490     {
491         *returned_language_table = language_table;
492     }
493     else
494     {
495         /* Free allocated memory when language loading failed. */
496         if (info.gx_binres_buffer)
497         {
498             _gx_system_memory_free(info.gx_binres_buffer);
499         }
500 
501         *returned_language_table = GX_NULL;
502     }
503 
504 
505     return status;
506 }
507 #endif
508 #endif
509 
510 /**************************************************************************/
511 /*                                                                        */
512 /*  FUNCTION                                               RELEASE        */
513 /*                                                                        */
514 /*    _gx_binres_language_table_load_ext                  PORTABLE C      */
515 /*                                                           6.1          */
516 /*  AUTHOR                                                                */
517 /*                                                                        */
518 /*    Kenneth Maxwell, Microsoft Corporation                              */
519 /*                                                                        */
520 /*  DESCRIPTION                                                           */
521 /*                                                                        */
522 /*    This service loads a language table from a binary data buffer.      */
523 /*                                                                        */
524 /*  INPUT                                                                 */
525 /*                                                                        */
526 /*    root_address                          Root address of binary        */
527 /*                                            resource data               */
528 /*    returned_language_table               Pointer to loaded language    */
529 /*                                           table                        */
530 /*                                                                        */
531 /*  OUTPUT                                                                */
532 /*                                                                        */
533 /*    Status                                Completion status             */
534 /*                                                                        */
535 /*  CALLS                                                                 */
536 /*                                                                        */
537 /*    _gx_binres_language_table_buffer_allocate                           */
538 /*                                          Allocate needed buffer for    */
539 /*                                            loading language table      */
540 /*    _gx_binres_resource_header_load                                     */
541 /*                                          Read resource header          */
542 /*    _gx_binres_string_header_load         Read string data header       */
543 /*    _gx_binres_language_header_load       Read language data header     */
544 /*    _gx_system_memory_free                Application defined memory    */
545 /*                                            free function               */
546 /*                                                                        */
547 /*  CALLED BY                                                             */
548 /*                                                                        */
549 /*    Application Code                                                    */
550 /*                                                                        */
551 /*  RELEASE HISTORY                                                       */
552 /*                                                                        */
553 /*    DATE              NAME                      DESCRIPTION             */
554 /*                                                                        */
555 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
556 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
557 /*                                            resulting in version 6.1    */
558 /*                                                                        */
559 /**************************************************************************/
560 #ifdef GX_BINARY_RESOURCE_SUPPORT
_gx_binres_language_table_load_ext(GX_UBYTE * root_address,GX_STRING *** returned_language_table)561 UINT _gx_binres_language_table_load_ext(GX_UBYTE *root_address, GX_STRING ***returned_language_table)
562 {
563 UINT                status;
564 GX_BINRES_DATA_INFO info;
565 GX_RESOURCE_HEADER  header;
566 GX_STRING_HEADER    string_header;
567 GX_LANGUAGE_HEADER  language_header;
568 GX_STRING         **language_table;
569 UINT                lang_index;
570 UINT                string_index;
571 USHORT              string_length;
572 GX_UBYTE           *get_data;
573 
574     memset(&info, 0, sizeof(GX_BINRES_DATA_INFO));
575 
576     info.gx_binres_root_address = root_address;
577 
578     /* Allocate memory that needed for language table.  */
579     status = _gx_binres_language_table_buffer_allocate(&info, sizeof(GX_STRING *), sizeof(GX_STRING));
580 
581     /* Read Resource header. */
582     info.gx_binres_read_offset = 0;
583     _gx_binres_resource_header_load(&info, &header);
584 
585     /* Skip theme info.  */
586     info.gx_binres_read_offset += header.gx_resource_header_theme_data_size;
587 
588     if (header.gx_resource_header_magic_number != GX_MAGIC_NUMBER)
589     {
590         return GX_INVALID_FORMAT;
591     }
592 
593     language_table = GX_NULL;
594 
595     /* Read language table.  */
596     if (status == GX_SUCCESS)
597     {
598         /* Read string header. */
599         _gx_binres_string_header_load(&info, &string_header);
600 
601         language_table = (GX_STRING **)(info.gx_binres_buffer + info.gx_binres_buffer_index);
602         info.gx_binres_buffer_index += sizeof(GX_STRING *) * string_header.gx_string_header_language_count;
603 
604         for (lang_index = 0; lang_index < string_header.gx_string_header_language_count; lang_index++)
605         {
606             /* Read language header.  */
607             _gx_binres_language_header_load(&info, &language_header);
608 
609             if (language_header.gx_language_header_magic_number != GX_MAGIC_NUMBER)
610             {
611                 status = GX_INVALID_FORMAT;
612                 break;
613             }
614 
615             /* Read string table.  */
616             language_table[lang_index] = (GX_STRING *)(info.gx_binres_buffer + info.gx_binres_buffer_index);
617             info.gx_binres_buffer_index += sizeof(GX_STRING) * string_header.gx_string_header_string_count;
618 
619             for (string_index = 1; string_index < string_header.gx_string_header_string_count; string_index++)
620             {
621                 /* Read string length. */
622                 get_data = info.gx_binres_root_address + info.gx_binres_read_offset;
623                 string_length = *(get_data + 1);
624                 string_length = (USHORT)(string_length << 8);
625                 string_length = (USHORT)(string_length | (*get_data));
626                 info.gx_binres_read_offset += sizeof(USHORT);
627 
628                 if (string_length)
629                 {
630                     language_table[lang_index][string_index].gx_string_ptr = (GX_CHAR *)(info.gx_binres_root_address + info.gx_binres_read_offset);
631                 }
632                 else
633                 {
634                     language_table[lang_index][string_index].gx_string_ptr = GX_NULL;
635                 }
636 
637                 language_table[lang_index][string_index].gx_string_length = string_length;
638                 info.gx_binres_read_offset += (UINT)(string_length + 1);
639             }
640         }
641     }
642 
643     if (status == GX_SUCCESS)
644     {
645         *returned_language_table = language_table;
646     }
647     else
648     {
649         /* Free allocated memory when language loading failed. */
650         if (info.gx_binres_buffer)
651         {
652             _gx_system_memory_free(info.gx_binres_buffer);
653         }
654 
655         *returned_language_table = GX_NULL;
656     }
657 
658 
659     return status;
660 }
661 #endif
662 
663