GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_system_private_string.c Lines: 151 151 100.0 %
Date: 2026-03-06 19:21:09 Branches: 96 96 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 **************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** GUIX Component                                                        */
17
/**                                                                       */
18
/**   Prompt Management (Prompt)                                          */
19
/**                                                                       */
20
/**************************************************************************/
21
22
#define GX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
#include "gx_api.h"
27
#include "gx_system.h"
28
#include "gx_utility.h"
29
30
/**************************************************************************/
31
/*                                                                        */
32
/*  FUNCTION                                               RELEASE        */
33
/*                                                                        */
34
/*    _gx_system_private_string_copy                      PORTABLE C      */
35
/*                                                           6.1          */
36
/*  AUTHOR                                                                */
37
/*                                                                        */
38
/*    Kenneth Maxwell, Microsoft Corporation                              */
39
/*                                                                        */
40
/*  DESCRIPTION                                                           */
41
/*                                                                        */
42
/*    This service makes a private copy of text assigned to a widget.     */
43
/*                                                                        */
44
/*                                                                        */
45
/*  INPUT                                                                 */
46
/*                                                                        */
47
/*    string                                Address of widget's text      */
48
/*                                            pointer                     */
49
/*    text                                  Pointer to string             */
50
/*                                                                        */
51
/*  OUTPUT                                                                */
52
/*                                                                        */
53
/*    status                                Completion status             */
54
/*                                                                        */
55
/*  CALLS                                                                 */
56
/*                                                                        */
57
/*    _gx_utility_string_length_check       Test string length            */
58
/*    _gx_system_memory_allocator           Allocate dynamic memory       */
59
/*    _gx_system_memory_free                Deallocate dynamic memory     */
60
/*                                                                        */
61
/*  CALLED BY                                                             */
62
/*                                                                        */
63
/*    GUIX internal code                                                  */
64
/*                                                                        */
65
/**************************************************************************/
66
46
UINT _gx_system_private_string_copy(GX_STRING *string, GX_CONST GX_STRING *text)
67
{
68
GX_UBYTE *byte;
69
USHORT    current_buffer_size;
70
USHORT    needed_buffer_size;
71
72
46
    if (_gx_system_memory_allocator == GX_NULL)
73
    {
74
4
        string -> gx_string_ptr = GX_NULL;
75
4
        string -> gx_string_length = 0;
76
4
        return GX_SYSTEM_MEMORY_ERROR;
77
    }
78
79
    /* are we assigning a non-NULL string? */
80

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