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