xref: /reactos/sdk/lib/ucrt/mbstring/mbsupr.cpp (revision 04e0dc4a)
1*04e0dc4aSTimo Kreuzer /***
2*04e0dc4aSTimo Kreuzer *mbsupr.c - Convert string upper case (MBCS)
3*04e0dc4aSTimo Kreuzer *
4*04e0dc4aSTimo Kreuzer *       Copyright (c) Microsoft Corporation.  All rights reserved.
5*04e0dc4aSTimo Kreuzer *
6*04e0dc4aSTimo Kreuzer *Purpose:
7*04e0dc4aSTimo Kreuzer *       Convert string upper case (MBCS)
8*04e0dc4aSTimo Kreuzer *
9*04e0dc4aSTimo Kreuzer *******************************************************************************/
10*04e0dc4aSTimo Kreuzer #ifndef _MBCS
11*04e0dc4aSTimo Kreuzer     #error This file should only be compiled with _MBCS defined
12*04e0dc4aSTimo Kreuzer #endif
13*04e0dc4aSTimo Kreuzer 
14*04e0dc4aSTimo Kreuzer #include <corecrt_internal_mbstring.h>
15*04e0dc4aSTimo Kreuzer #include <corecrt_internal_securecrt.h>
16*04e0dc4aSTimo Kreuzer #include <locale.h>
17*04e0dc4aSTimo Kreuzer #include <string.h>
18*04e0dc4aSTimo Kreuzer 
19*04e0dc4aSTimo Kreuzer #pragma warning(disable:__WARNING_POTENTIAL_BUFFER_OVERFLOW_NULLTERMINATED)
20*04e0dc4aSTimo Kreuzer 
21*04e0dc4aSTimo Kreuzer /***
22*04e0dc4aSTimo Kreuzer * _mbsupr - Convert string upper case (MBCS)
23*04e0dc4aSTimo Kreuzer *
24*04e0dc4aSTimo Kreuzer *Purpose:
25*04e0dc4aSTimo Kreuzer *       Converts all the lower case characters in a string
26*04e0dc4aSTimo Kreuzer *       to upper case in place.   Handles MBCS chars correctly.
27*04e0dc4aSTimo Kreuzer *
28*04e0dc4aSTimo Kreuzer *Entry:
29*04e0dc4aSTimo Kreuzer *       unsigned char *string = pointer to string
30*04e0dc4aSTimo Kreuzer *
31*04e0dc4aSTimo Kreuzer *Exit:
32*04e0dc4aSTimo Kreuzer *       Returns a pointer to the input string.
33*04e0dc4aSTimo Kreuzer *       Returns nullptr on error.
34*04e0dc4aSTimo Kreuzer *
35*04e0dc4aSTimo Kreuzer *Exceptions:
36*04e0dc4aSTimo Kreuzer *       Input parameters are validated. Refer to the validation section of the function.
37*04e0dc4aSTimo Kreuzer *
38*04e0dc4aSTimo Kreuzer *******************************************************************************/
39*04e0dc4aSTimo Kreuzer 
_mbsupr_s_l(unsigned char * string,size_t sizeInBytes,_locale_t plocinfo)40*04e0dc4aSTimo Kreuzer extern "C" errno_t __cdecl _mbsupr_s_l(
41*04e0dc4aSTimo Kreuzer         unsigned char *string,
42*04e0dc4aSTimo Kreuzer         size_t sizeInBytes,
43*04e0dc4aSTimo Kreuzer         _locale_t plocinfo
44*04e0dc4aSTimo Kreuzer         )
45*04e0dc4aSTimo Kreuzer {
46*04e0dc4aSTimo Kreuzer         size_t stringlen;
47*04e0dc4aSTimo Kreuzer 
48*04e0dc4aSTimo Kreuzer         /* validation section */
49*04e0dc4aSTimo Kreuzer         _VALIDATE_RETURN_ERRCODE((string != nullptr && sizeInBytes > 0) || (string == nullptr && sizeInBytes == 0), EINVAL);
50*04e0dc4aSTimo Kreuzer 
51*04e0dc4aSTimo Kreuzer         if (string == nullptr)
52*04e0dc4aSTimo Kreuzer         {
53*04e0dc4aSTimo Kreuzer             /* nothing to do */
54*04e0dc4aSTimo Kreuzer             return 0;
55*04e0dc4aSTimo Kreuzer         }
56*04e0dc4aSTimo Kreuzer 
57*04e0dc4aSTimo Kreuzer         stringlen = strnlen((char *)string, sizeInBytes);
58*04e0dc4aSTimo Kreuzer         if (stringlen >= sizeInBytes)
59*04e0dc4aSTimo Kreuzer         {
60*04e0dc4aSTimo Kreuzer             _RESET_STRING(string, sizeInBytes);
61*04e0dc4aSTimo Kreuzer             _RETURN_DEST_NOT_NULL_TERMINATED(string, sizeInBytes);
62*04e0dc4aSTimo Kreuzer         }
63*04e0dc4aSTimo Kreuzer         _FILL_STRING(string, sizeInBytes, stringlen + 1);
64*04e0dc4aSTimo Kreuzer 
65*04e0dc4aSTimo Kreuzer         unsigned char *cp, *dst;
66*04e0dc4aSTimo Kreuzer         _LocaleUpdate _loc_update(plocinfo);
67*04e0dc4aSTimo Kreuzer 
68*04e0dc4aSTimo Kreuzer         for (cp = string, dst = string; *cp; ++cp)
69*04e0dc4aSTimo Kreuzer         {
70*04e0dc4aSTimo Kreuzer             if ( _ismbblead_l(*cp, _loc_update.GetLocaleT()) )
71*04e0dc4aSTimo Kreuzer             {
72*04e0dc4aSTimo Kreuzer 
73*04e0dc4aSTimo Kreuzer 
74*04e0dc4aSTimo Kreuzer                 int retval;
75*04e0dc4aSTimo Kreuzer                 unsigned char ret[4];
76*04e0dc4aSTimo Kreuzer 
77*04e0dc4aSTimo Kreuzer                 if ( (retval = __acrt_LCMapStringA(
78*04e0dc4aSTimo Kreuzer                                 _loc_update.GetLocaleT(),
79*04e0dc4aSTimo Kreuzer                                 _loc_update.GetLocaleT()->mbcinfo->mblocalename,
80*04e0dc4aSTimo Kreuzer                                 LCMAP_UPPERCASE,
81*04e0dc4aSTimo Kreuzer                                 (const char *)cp,
82*04e0dc4aSTimo Kreuzer                                 2,
83*04e0dc4aSTimo Kreuzer                                 (char *)ret,
84*04e0dc4aSTimo Kreuzer                                 2,
85*04e0dc4aSTimo Kreuzer                                 _loc_update.GetLocaleT()->mbcinfo->mbcodepage,
86*04e0dc4aSTimo Kreuzer                                 TRUE )) == 0 )
87*04e0dc4aSTimo Kreuzer                 {
88*04e0dc4aSTimo Kreuzer                     errno = EILSEQ;
89*04e0dc4aSTimo Kreuzer                     _RESET_STRING(string, sizeInBytes);
90*04e0dc4aSTimo Kreuzer                     return errno;
91*04e0dc4aSTimo Kreuzer                 }
92*04e0dc4aSTimo Kreuzer 
93*04e0dc4aSTimo Kreuzer                 *(dst++) = ret[0];
94*04e0dc4aSTimo Kreuzer                 ++cp;
95*04e0dc4aSTimo Kreuzer                 if (retval > 1)
96*04e0dc4aSTimo Kreuzer                 {
97*04e0dc4aSTimo Kreuzer                     *(dst++) = ret[1];
98*04e0dc4aSTimo Kreuzer                 }
99*04e0dc4aSTimo Kreuzer 
100*04e0dc4aSTimo Kreuzer 
101*04e0dc4aSTimo Kreuzer             }
102*04e0dc4aSTimo Kreuzer             else
103*04e0dc4aSTimo Kreuzer                 /* single byte, macro version */
104*04e0dc4aSTimo Kreuzer                 *(dst++) = (unsigned char) _mbbtoupper_l(*cp, _loc_update.GetLocaleT());
105*04e0dc4aSTimo Kreuzer         }
106*04e0dc4aSTimo Kreuzer         /* null terminate the string */
107*04e0dc4aSTimo Kreuzer         *dst = '\0';
108*04e0dc4aSTimo Kreuzer 
109*04e0dc4aSTimo Kreuzer         return 0;
110*04e0dc4aSTimo Kreuzer }
111*04e0dc4aSTimo Kreuzer 
errno_t(__cdecl _mbsupr_s)112*04e0dc4aSTimo Kreuzer extern "C" errno_t (__cdecl _mbsupr_s)(
113*04e0dc4aSTimo Kreuzer         unsigned char *string,
114*04e0dc4aSTimo Kreuzer         size_t sizeInBytes
115*04e0dc4aSTimo Kreuzer         )
116*04e0dc4aSTimo Kreuzer {
117*04e0dc4aSTimo Kreuzer     return _mbsupr_s_l(string, sizeInBytes, nullptr);
118*04e0dc4aSTimo Kreuzer }
119*04e0dc4aSTimo Kreuzer 
120*04e0dc4aSTimo Kreuzer extern "C" unsigned char * (__cdecl _mbsupr_l)(
121*04e0dc4aSTimo Kreuzer         unsigned char *string,
122*04e0dc4aSTimo Kreuzer         _locale_t plocinfo
123*04e0dc4aSTimo Kreuzer         )
124*04e0dc4aSTimo Kreuzer {
125*04e0dc4aSTimo Kreuzer     return (_mbsupr_s_l(string, (string == nullptr ? 0 : (size_t)-1), plocinfo) == 0 ? string : nullptr);
126*04e0dc4aSTimo Kreuzer }
127*04e0dc4aSTimo Kreuzer 
128*04e0dc4aSTimo Kreuzer extern "C" unsigned char * (__cdecl _mbsupr)(
129*04e0dc4aSTimo Kreuzer         unsigned char *string
130*04e0dc4aSTimo Kreuzer         )
131*04e0dc4aSTimo Kreuzer {
132*04e0dc4aSTimo Kreuzer     return (_mbsupr_s_l(string, (string == nullptr ? 0 : (size_t)-1), nullptr) == 0 ? string : nullptr);
133*04e0dc4aSTimo Kreuzer }
134