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 /** Prompt Management (Prompt) */
18 /** */
19 /**************************************************************************/
20
21 #define GX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25 #include "gx_api.h"
26 #include "gx_system.h"
27 #include "gx_utility.h"
28
29 /**************************************************************************/
30 /* */
31 /* FUNCTION RELEASE */
32 /* */
33 /* _gx_system_private_string_copy PORTABLE C */
34 /* 6.1 */
35 /* AUTHOR */
36 /* */
37 /* Kenneth Maxwell, Microsoft Corporation */
38 /* */
39 /* DESCRIPTION */
40 /* */
41 /* This service makes a private copy of text assigned to a widget. */
42 /* */
43 /* */
44 /* INPUT */
45 /* */
46 /* string Address of widget's text */
47 /* pointer */
48 /* text Pointer to string */
49 /* */
50 /* OUTPUT */
51 /* */
52 /* status Completion status */
53 /* */
54 /* CALLS */
55 /* */
56 /* _gx_utility_string_length_check Test string length */
57 /* _gx_system_memory_allocator Allocate dynamic memory */
58 /* _gx_system_memory_free Deallocate dynamic memory */
59 /* */
60 /* CALLED BY */
61 /* */
62 /* GUIX internal code */
63 /* */
64 /* RELEASE HISTORY */
65 /* */
66 /* DATE NAME DESCRIPTION */
67 /* */
68 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
69 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
70 /* resulting in version 6.1 */
71 /* */
72 /**************************************************************************/
_gx_system_private_string_copy(GX_STRING * string,GX_CONST GX_STRING * text)73 UINT _gx_system_private_string_copy(GX_STRING *string, GX_CONST GX_STRING *text)
74 {
75 GX_UBYTE *byte;
76 USHORT current_buffer_size;
77 USHORT needed_buffer_size;
78
79 if (_gx_system_memory_allocator == GX_NULL)
80 {
81 string -> gx_string_ptr = GX_NULL;
82 string -> gx_string_length = 0;
83 return GX_SYSTEM_MEMORY_ERROR;
84 }
85
86 /* are we assigning a non-NULL string? */
87 if (text && text -> gx_string_ptr)
88 {
89 GX_UTILITY_USHORT_CHECK(text -> gx_string_length)
90 GX_UTILITY_MATH_USHORT_ADD((USHORT)text -> gx_string_length, 3, needed_buffer_size)
91 }
92 else
93 {
94 needed_buffer_size = 0;
95 }
96
97 if (needed_buffer_size)
98 {
99 /* check to see if we have already allocated sufficient memory */
100 if (string -> gx_string_ptr)
101 {
102 byte = (GX_UBYTE *)string -> gx_string_ptr;
103 current_buffer_size = *byte++;
104 current_buffer_size = (USHORT)(current_buffer_size << 8);
105 current_buffer_size = (USHORT)(current_buffer_size | (*byte++));
106
107 if (current_buffer_size < needed_buffer_size)
108 {
109 /* if our buffer is not large enough, free the current buffer */
110 _gx_system_memory_free((void *)string -> gx_string_ptr);
111
112 /* and attempt to allocate a new buffer */
113 string -> gx_string_ptr = (GX_CHAR *)_gx_system_memory_allocator(needed_buffer_size);
114
115 /* if buffer allocation succeeded, update our buffer size and copy the string */
116 if (string -> gx_string_ptr)
117 {
118 byte = (GX_UBYTE *)string -> gx_string_ptr;
119 *byte++ = (GX_UBYTE)(needed_buffer_size >> 8);
120 *byte++ = (GX_UBYTE)(needed_buffer_size & 0xff);
121
122 memcpy(byte, text -> gx_string_ptr, text -> gx_string_length + 1); /* Use case of memcpy is verified. */
123 string -> gx_string_length = text -> gx_string_length;
124 }
125 else
126 {
127 string -> gx_string_length = 0;
128 }
129 }
130 else
131 {
132 /* the existing buffer is large enough, just copy the string without updating buffer size */
133 memcpy(byte, text -> gx_string_ptr, text -> gx_string_length + 1); /* Use case of memcpy is verified. */
134 string -> gx_string_length = text -> gx_string_length;
135 }
136 }
137 else
138 {
139 /* the current buffer is NULL, attempt to allocate a new buffer */
140 string -> gx_string_ptr = (GX_CHAR *)_gx_system_memory_allocator(needed_buffer_size);
141
142 /* if buffer allocation succeeded, update our buffer size and copy the string */
143 if (string -> gx_string_ptr)
144 {
145 byte = (GX_UBYTE *)string -> gx_string_ptr;
146 *byte++ = (GX_UBYTE)(needed_buffer_size >> 8);
147 *byte++ = (GX_UBYTE)(needed_buffer_size & 0xff);
148
149 memcpy(byte, text -> gx_string_ptr, text -> gx_string_length + 1); /* Use case of memcpy is verified. */
150 string -> gx_string_length = text -> gx_string_length;
151 }
152 else
153 {
154 string -> gx_string_length = 0;
155 }
156 }
157 }
158 else
159 {
160 /* here if the new text is GX_NULL, free our buffer if one has been allocated */
161 if (string -> gx_string_ptr)
162 {
163 _gx_system_memory_free((void *)string -> gx_string_ptr);
164 string -> gx_string_ptr = GX_NULL;
165 }
166
167 string -> gx_string_length = 0;
168 return GX_SUCCESS;
169 }
170 if (string -> gx_string_ptr)
171 {
172 return(GX_SUCCESS);
173 }
174 return GX_SYSTEM_MEMORY_ERROR;
175 }
176
177 /**************************************************************************/
178 /* */
179 /* FUNCTION RELEASE */
180 /* */
181 /* _gx_system_private_string_list_copy PORTABLE C */
182 /* 6.1 */
183 /* AUTHOR */
184 /* */
185 /* Kenneth Maxwell, Microsoft Corporation */
186 /* */
187 /* DESCRIPTION */
188 /* */
189 /* This service makes a private copy of string list assigned to a */
190 /* widget. */
191 /* */
192 /* */
193 /* INPUT */
194 /* */
195 /* ptr_address Address of widget's string */
196 /* list pointer */
197 /* string_list Pointer to string list */
198 /* string_count Number of string in list */
199 /* */
200 /* OUTPUT */
201 /* */
202 /* status Completion status */
203 /* */
204 /* CALLS */
205 /* */
206 /* _gx_utility_string_length_check Test string length */
207 /* _gx_system_memory_allocator Allocate dynamic memory */
208 /* _gx_system_memory_free Deallocate dynamic memory */
209 /* */
210 /* CALLED BY */
211 /* */
212 /* GUIX internal code */
213 /* */
214 /* RELEASE HISTORY */
215 /* */
216 /* DATE NAME DESCRIPTION */
217 /* */
218 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
219 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
220 /* resulting in version 6.1 */
221 /* */
222 /**************************************************************************/
223 #if defined(GX_ENABLE_DEPRECATED_STRING_API)
_gx_system_private_string_list_copy(GX_CONST GX_CHAR *** ptr_address,GX_CONST GX_CHAR ** string_list,INT string_count)224 UINT _gx_system_private_string_list_copy(GX_CONST GX_CHAR ***ptr_address, GX_CONST GX_CHAR **string_list, INT string_count)
225 {
226 UINT status;
227 GX_UBYTE *byte;
228 USHORT current_buffer_size;
229 USHORT needed_buffer_size;
230 INT index;
231 GX_CHAR **list_ptr;
232 GX_CHAR *string_ptr;
233 UINT length;
234
235 list_ptr = (GX_CHAR **)*ptr_address;
236
237 if (_gx_system_memory_allocator == GX_NULL)
238 {
239 *ptr_address = GX_NULL;
240 return GX_SYSTEM_MEMORY_ERROR;
241 }
242
243 /* are we assigning a non-NULL string array? */
244 if (string_list)
245 {
246 /* calculate size of needed buffer. buffer size for holding each string pointer +
247 2 byte size +
248 buffer size of each string. */
249 GX_UTILITY_USHORT_CHECK(string_count)
250 GX_UTILITY_MATH_USHORT_MULT((USHORT)string_count, sizeof(GX_CHAR *), needed_buffer_size)
251
252 /* As string_count is an integer, the maximum needed_buffer_size is 65532,
253 so that needed_buffer_size can not be overflow. */
254 needed_buffer_size = (USHORT)(needed_buffer_size + 2);
255
256 for (index = 0; index < string_count; index++)
257 {
258 if (string_list[index])
259 {
260 status = _gx_utility_string_length_check(string_list[index], &length, GX_MAX_STRING_LENGTH);
261
262 if (status != GX_SUCCESS)
263 {
264 return status;
265 }
266
267 GX_UTILITY_USHORT_CHECK(length)
268 GX_UTILITY_MATH_USHORT_ADD(needed_buffer_size, (USHORT)length, needed_buffer_size)
269 GX_UTILITY_MATH_USHORT_ADD(needed_buffer_size, 1, needed_buffer_size)
270 }
271 }
272 }
273 else
274 {
275 needed_buffer_size = 0;
276 }
277
278 if (needed_buffer_size)
279 {
280 /* check to see if we have already allocated sufficient memory */
281 if (list_ptr)
282 {
283 byte = (GX_UBYTE *)list_ptr;
284 current_buffer_size = *byte++;
285 current_buffer_size = (USHORT)(current_buffer_size << 8);
286 current_buffer_size = (USHORT)(current_buffer_size | (*byte++));
287
288 if (current_buffer_size < needed_buffer_size)
289 {
290 /* if our buffer is not large enough, free the current buffer */
291 _gx_system_memory_free((void *)list_ptr);
292
293 /* and attempt to allocate a new buffer */
294 list_ptr = (GX_CHAR **)_gx_system_memory_allocator(needed_buffer_size);
295 }
296 }
297 else
298 {
299 /* the current buffer is NULL, attempt to allocate a new buffer */
300 list_ptr = (GX_CHAR **)_gx_system_memory_allocator(needed_buffer_size);
301 }
302
303 if (list_ptr)
304 {
305 *ptr_address = (GX_CONST GX_CHAR **)list_ptr;
306 byte = (GX_UBYTE *)list_ptr;
307 *byte++ = (GX_UBYTE)(needed_buffer_size >> 8);
308 *byte++ = (GX_UBYTE)(needed_buffer_size & 0xff);
309
310 list_ptr = (GX_CHAR **)byte;
311 string_ptr = (GX_CHAR *)(byte + ((INT)sizeof(GX_CHAR *)) * string_count);
312
313 for (index = 0; index < string_count; index++)
314 {
315 list_ptr[index] = string_ptr;
316
317 if (string_list[index])
318 {
319 /* Get string length. */
320 _gx_utility_string_length_check(string_list[index], &length, GX_MAX_STRING_LENGTH);
321
322 memcpy((VOID *)string_ptr, string_list[index], length + 1); /* Use case of memcpy is verified. */
323 }
324 else
325 {
326 *string_ptr = '\0';
327 length = 0;
328 }
329
330 string_ptr += length + 1;
331 }
332 }
333 }
334 else
335 {
336 /* here if the new text is GX_NULL, free our buffer if one has been allocated */
337 if (list_ptr)
338 {
339 _gx_system_memory_free((void *)list_ptr);
340 *ptr_address = GX_NULL;
341 }
342 return GX_SUCCESS;
343 }
344 if (list_ptr)
345 {
346 return(GX_SUCCESS);
347 }
348 return GX_SYSTEM_MEMORY_ERROR;
349 }
350 #endif
351
352 /**************************************************************************/
353 /* */
354 /* FUNCTION RELEASE */
355 /* */
356 /* _gx_system_private_string_list_copy_ext PORTABLE C */
357 /* 6.1 */
358 /* AUTHOR */
359 /* */
360 /* Kenneth Maxwell, Microsoft Corporation */
361 /* */
362 /* DESCRIPTION */
363 /* */
364 /* This service makes a private copy of string list assigned to a */
365 /* widget. */
366 /* */
367 /* */
368 /* INPUT */
369 /* */
370 /* ptr_address Address of widget's string */
371 /* list pointer */
372 /* buffer_size String list buffer size */
373 /* string_list Pointer to string list */
374 /* string_count Number of string in list */
375 /* */
376 /* OUTPUT */
377 /* */
378 /* status Completion status */
379 /* */
380 /* CALLS */
381 /* */
382 /* _gx_system_memory_allocator Allocate dynamic memory */
383 /* _gx_system_memory_free Deallocate dynamic memory */
384 /* */
385 /* CALLED BY */
386 /* */
387 /* GUIX internal code */
388 /* */
389 /* RELEASE HISTORY */
390 /* */
391 /* DATE NAME DESCRIPTION */
392 /* */
393 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
394 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
395 /* resulting in version 6.1 */
396 /* */
397 /**************************************************************************/
_gx_system_private_string_list_copy_ext(GX_STRING ** ptr_address,USHORT * buffer_size,GX_CONST GX_STRING * string_list,INT string_count)398 UINT _gx_system_private_string_list_copy_ext(GX_STRING **ptr_address, USHORT *buffer_size, GX_CONST GX_STRING *string_list, INT string_count)
399 {
400 USHORT current_buffer_size;
401 USHORT needed_buffer_size;
402 INT index;
403 GX_STRING *list_ptr;
404 GX_CONST GX_CHAR *string_ptr;
405 UINT length;
406
407 list_ptr = *ptr_address;
408
409 if (_gx_system_memory_allocator == GX_NULL)
410 {
411 return GX_SYSTEM_MEMORY_ERROR;
412 }
413
414 /* are we assigning a non-NULL string array? */
415 if (string_list)
416 {
417 /* calculate size of needed buffer. buffer size for holding each string pointer +
418 buffer size of each string. */
419 needed_buffer_size = (USHORT)(((INT)sizeof(GX_STRING)) * string_count);
420 for (index = 0; index < string_count; index++)
421 {
422 if (string_list[index].gx_string_ptr)
423 {
424 GX_UTILITY_USHORT_CHECK(string_list[index].gx_string_length)
425 GX_UTILITY_MATH_USHORT_ADD(needed_buffer_size, (USHORT)string_list[index].gx_string_length, needed_buffer_size)
426 GX_UTILITY_MATH_USHORT_ADD(needed_buffer_size, 1, needed_buffer_size)
427 }
428 }
429 }
430 else
431 {
432 needed_buffer_size = 0;
433 }
434
435 if (needed_buffer_size)
436 {
437 /* check to see if we have already allocated sufficient memory */
438 if (list_ptr)
439 {
440 current_buffer_size = *buffer_size;
441
442 if (current_buffer_size < needed_buffer_size)
443 {
444 /* if our buffer is not large enough, free the current buffer */
445 _gx_system_memory_free((void *)list_ptr);
446
447 /* and attempt to allocate a new buffer */
448 list_ptr = (GX_STRING *)_gx_system_memory_allocator(needed_buffer_size);
449 *buffer_size = needed_buffer_size;
450 }
451 }
452 else
453 {
454 /* the current buffer is NULL, attempt to allocate a new buffer */
455 list_ptr = (GX_STRING *)_gx_system_memory_allocator(needed_buffer_size);
456 *buffer_size = needed_buffer_size;
457 }
458
459 if (list_ptr)
460 {
461 *ptr_address = list_ptr;
462
463 string_ptr = (GX_CONST GX_CHAR *)(list_ptr + string_count);
464
465 for (index = 0; index < string_count; index++)
466 {
467 length = string_list[index].gx_string_length;
468
469 list_ptr[index].gx_string_ptr = string_ptr;
470 list_ptr[index].gx_string_length = length;
471
472 if (string_list[index].gx_string_ptr)
473 {
474 memcpy((VOID *)string_ptr, string_list[index].gx_string_ptr, length + 1); /* Use case of memcpy is verified. */
475 string_ptr += length + 1;
476 }
477 }
478 }
479 }
480 else
481 {
482 /* here if the new text is GX_NULL, free our buffer if one has been allocated */
483 if (list_ptr)
484 {
485 _gx_system_memory_free((void *)list_ptr);
486 *ptr_address = GX_NULL;
487 *buffer_size = 0;
488 }
489 return GX_SUCCESS;
490 }
491 if (list_ptr)
492 {
493 return(GX_SUCCESS);
494 }
495
496 return GX_SYSTEM_MEMORY_ERROR;
497 }
498
499 /**************************************************************************/
500 /* */
501 /* FUNCTION RELEASE */
502 /* */
503 /* _gx_system_private_string_get PORTABLE C */
504 /* 6.1 */
505 /* AUTHOR */
506 /* */
507 /* Kenneth Maxwell, Microsoft Corporation */
508 /* */
509 /* DESCRIPTION */
510 /* */
511 /* This service returns the string pointer in a dynamically copied */
512 /* string buffer. */
513 /* */
514 /* */
515 /* INPUT */
516 /* */
517 /* buffer string buffer address */
518 /* style calling widget style */
519 /* */
520 /* OUTPUT */
521 /* */
522 /* None */
523 /* */
524 /* CALLS */
525 /* */
526 /* */
527 /* CALLED BY */
528 /* */
529 /* _gx_checkbox_draw */
530 /* */
531 /* RELEASE HISTORY */
532 /* */
533 /* DATE NAME DESCRIPTION */
534 /* */
535 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
536 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
537 /* resulting in version 6.1 */
538 /* */
539 /**************************************************************************/
_gx_system_private_string_get(GX_CONST GX_STRING * input,GX_STRING * output,ULONG style)540 VOID _gx_system_private_string_get(GX_CONST GX_STRING *input, GX_STRING *output, ULONG style)
541 {
542 GX_UBYTE *temp;
543
544 output -> gx_string_ptr = GX_NULL;
545 output -> gx_string_length = 0;
546
547 if (input -> gx_string_ptr == GX_NULL)
548 {
549 return;
550 }
551
552 if (style & GX_STYLE_TEXT_COPY)
553 {
554 /* If the string has been dynamically copied, then the first two bytes of
555 the string buffer hold the buffer size. Skip those bytes and return
556 pointer to the actual string
557 */
558 temp = (GX_UBYTE *)input -> gx_string_ptr;
559 temp += 2;
560 output -> gx_string_ptr = (GX_CHAR *)temp;
561 output -> gx_string_length = input -> gx_string_length;
562 }
563 else
564 {
565 /* No dynamic copy, the buffer is the string */
566 output -> gx_string_ptr = input -> gx_string_ptr;
567 output -> gx_string_length = input -> gx_string_length;
568 }
569 }
570
571 /**************************************************************************/
572 /* */
573 /* FUNCTION RELEASE */
574 /* */
575 /* _gx_system_private_string_list_get PORTABLE C */
576 /* 6.1 */
577 /* AUTHOR */
578 /* */
579 /* Kenneth Maxwell, Microsoft Corporation */
580 /* */
581 /* DESCRIPTION */
582 /* */
583 /* This service returns the string pointer in a dynamically copied */
584 /* string buffer. */
585 /* */
586 /* */
587 /* INPUT */
588 /* */
589 /* buffer string buffer address */
590 /* style calling widget style */
591 /* */
592 /* OUTPUT */
593 /* */
594 /* None */
595 /* */
596 /* CALLS */
597 /* */
598 /* */
599 /* CALLED BY */
600 /* */
601 /* _gx_checkbox_draw */
602 /* */
603 /* RELEASE HISTORY */
604 /* */
605 /* DATE NAME DESCRIPTION */
606 /* */
607 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
608 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
609 /* resulting in version 6.1 */
610 /* */
611 /**************************************************************************/
612 #if defined(GX_ENABLE_DEPRECATED_STRING_API)
_gx_system_private_string_list_get(GX_CONST GX_CHAR ** input,GX_CONST GX_CHAR *** output,ULONG style)613 VOID _gx_system_private_string_list_get(GX_CONST GX_CHAR **input, GX_CONST GX_CHAR ***output, ULONG style)
614 {
615 GX_UBYTE *temp;
616
617 if (style & GX_STYLE_TEXT_COPY)
618 {
619 /* If the string has been dynamically copied, then the first two bytes of
620 the string buffer hold the buffer size. Skip those bytes and return
621 pointer to the actual string
622 */
623 temp = (GX_UBYTE *)input;
624 temp += 2;
625
626 *output = (GX_CONST GX_CHAR **)temp;
627 }
628 else
629 {
630 *output = input;
631 }
632 }
633 #endif
634
635