xref: /reactos/sdk/lib/ucrt/mbstring/mbscpy_s_l.cpp (revision 53d808d2)
1 /***
2 *mbscpy_s_l.c - Copy one string to another (MBCS)
3 *
4 *       Copyright (c) Microsoft Corporation.  All rights reserved.
5 *
6 *Purpose:
7 *       Copy one string to another (MBCS)
8 *
9 *******************************************************************************/
10 #ifndef _MBCS
11     #error This file should only be compiled with _MBCS defined
12 #endif
13 
14 #include <corecrt_internal_mbstring.h>
15 #include <corecrt_internal_securecrt.h>
16 
17 errno_t __cdecl _mbscpy_s_l(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, _LOCALE_ARG_DECL)
18 {
19     unsigned char *p;
20     size_t available;
21     BOOL fIsLeadPrefix;
22 
23     /* validation section */
24     _VALIDATE_STRING(_Dst, _SizeInBytes);
25     _VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes);
26 
27     _LOCALE_UPDATE;
28     if (_LOCALE_SHORTCUT_TEST)
29     {
30         return strcpy_s((char *)_Dst, _SizeInBytes, (const char *)_Src);
31     }
32 
33     p = _Dst;
34     available = _SizeInBytes;
35     while ((*p++ = *_Src++) != 0 && --available > 0)
36     {
37     }
38 
39     /*
40      * If we ran out of destination bytes then we did so before copying null.
41      * Only exception to that is if last mbc was invalid (leadbyte+null), which
42      * is treated as null. In that case clear the copied lead byte and return ok.
43      */
44 
45     if (available == 0)
46     {
47         if (*_Src == 0) {
48             _ISMBBLEADPREFIX(fIsLeadPrefix,_Dst,p-1);
49             if (fIsLeadPrefix)
50             {
51                 p[-1] = 0;
52                 _RETURN_MBCS_ERROR;
53             }
54         }
55         _RESET_STRING(_Dst, _SizeInBytes);
56         _RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes);
57     }
58 
59     /*
60      * Otherwise we have space left in the dst buffer and stopped copying because
61      * we saw a null in the src. If null is part of invalid MBC (lead byte + null)
62      * then clear the lead byte also.
63      */
64 
65     _ISMBBLEADPREFIX(fIsLeadPrefix, _Dst, p-2);
66     if (fIsLeadPrefix && (p - 2) >= _Dst)
67     {
68         p[-2] = 0;
69         available++;
70         _FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1);
71         _RETURN_MBCS_ERROR;
72     }
73 
74     _FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1);
75     _RETURN_NO_ERROR;
76 }
77