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