Commit fdcf03fb authored by Alexandre Julliard's avatar Alexandre Julliard

msvcrt: Unify the strncpy_s() and wcsncpy_s() implementations.

parent 3514e65f
...@@ -1271,39 +1271,45 @@ char* __cdecl strncpy(char *dst, const char *src, size_t len) ...@@ -1271,39 +1271,45 @@ char* __cdecl strncpy(char *dst, const char *src, size_t len)
/****************************************************************** /******************************************************************
* strncpy_s (MSVCRT.@) * strncpy_s (MSVCRT.@)
*/ */
int CDECL strncpy_s(char *dest, size_t numberOfElements, int __cdecl strncpy_s( char *dst, size_t elem, const char *src, size_t count )
const char *src, size_t count)
{ {
size_t i, end; char *p = dst;
BOOL truncate = (count == _TRUNCATE);
TRACE("(%p %Iu %s %Iu)\n", dest, numberOfElements, debugstr_a(src), count); TRACE("(%p %Iu %s %Iu)\n", dst, elem, debugstr_a(src), count);
if(!count) { if (!count)
if(dest && numberOfElements) {
*dest = 0; if (dst && elem) *dst = 0;
return 0; return 0;
} }
if (!MSVCRT_CHECK_PMT(dest != NULL)) return EINVAL; if (!MSVCRT_CHECK_PMT(dst != NULL)) return EINVAL;
if (!MSVCRT_CHECK_PMT(src != NULL)) return EINVAL; if (!MSVCRT_CHECK_PMT(elem != 0)) return EINVAL;
if (!MSVCRT_CHECK_PMT(numberOfElements != 0)) return EINVAL; if (!MSVCRT_CHECK_PMT(src != NULL))
{
if(count!=_TRUNCATE && count<numberOfElements) *dst = 0;
end = count; return EINVAL;
else
end = numberOfElements-1;
for(i=0; i<end && src[i]; i++)
dest[i] = src[i];
if(!src[i] || end==count || count==_TRUNCATE) {
dest[i] = '\0';
return 0;
} }
MSVCRT_INVALID_PMT("dest[numberOfElements] is too small", EINVAL); while (elem && count && *src)
dest[0] = '\0'; {
return EINVAL; *p++ = *src++;
elem--;
count--;
}
if (!elem && truncate)
{
*(p-1) = 0;
return STRUNCATE;
}
else if (!elem)
{
*dst = 0;
return ERANGE;
}
*p = 0;
return 0;
} }
/********************************************************************* /*********************************************************************
......
...@@ -64,6 +64,7 @@ static int (__cdecl *p_strncmp)(const char *, const char *, size_t); ...@@ -64,6 +64,7 @@ static int (__cdecl *p_strncmp)(const char *, const char *, size_t);
static int (__cdecl *p_strcpy)(char *dst, const char *src); static int (__cdecl *p_strcpy)(char *dst, const char *src);
static int (__cdecl *pstrcpy_s)(char *dst, size_t len, const char *src); static int (__cdecl *pstrcpy_s)(char *dst, size_t len, const char *src);
static int (__cdecl *pstrcat_s)(char *dst, size_t len, const char *src); static int (__cdecl *pstrcat_s)(char *dst, size_t len, const char *src);
static int (__cdecl *p_strncpy_s)(char *dst, size_t size, const char *src, size_t count);
static int (__cdecl *p_mbscat_s)(unsigned char *dst, size_t size, const unsigned char *src); static int (__cdecl *p_mbscat_s)(unsigned char *dst, size_t size, const unsigned char *src);
static int (__cdecl *p_mbsnbcat_s)(unsigned char *dst, size_t size, const unsigned char *src, size_t count); static int (__cdecl *p_mbsnbcat_s)(unsigned char *dst, size_t size, const unsigned char *src, size_t count);
static int (__cdecl *p_mbsnbcpy_s)(unsigned char * dst, size_t size, const unsigned char * src, size_t count); static int (__cdecl *p_mbsnbcpy_s)(unsigned char * dst, size_t size, const unsigned char * src, size_t count);
...@@ -738,6 +739,55 @@ static void test_strcpy_s(void) ...@@ -738,6 +739,55 @@ static void test_strcpy_s(void)
dest[4] == 'l' && dest[5] == '\0' && dest[6] == '\0' && dest[7] == 'X', dest[4] == 'l' && dest[5] == '\0' && dest[6] == '\0' && dest[7] == 'X',
"Unexpected return data from strcpy: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", "Unexpected return data from strcpy: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
if(!p_strncpy_s)
{
win_skip("strncpy_s not found\n");
return;
}
ret = p_strncpy_s(NULL, 18, big, ARRAY_SIZE(big));
ok(ret == EINVAL, "p_strncpy_s expect EINVAL got %d\n", ret);
dest[0] = 'A';
ret = p_strncpy_s(dest, 8, NULL, 1);
ok(ret == EINVAL, "expected EINVAL got %d\n", ret);
ok(dest[0] == 0, "dest[0] not 0\n");
dest[0] = 'A';
ret = p_strncpy_s(dest, 8, NULL, 0);
ok(ret == 0, "expected ERROR_SUCCESS got %d\n", ret);
ok(dest[0] == 0, "dest[0] not 0\n");
dest[0] = 'A';
ret = p_strncpy_s(dest, 0, big, ARRAY_SIZE(big));
ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
ok(dest[0] == 0 || ret == EINVAL, "dest[0] not 0\n");
ret = p_strncpy_s(dest, 8, small, ARRAY_SIZE(small));
ok(ret == 0, "expected 0 got %d\n", ret);
ok(!strcmp(dest, small), "dest != small\n");
dest[0] = 'A';
ret = p_strncpy_s(dest, 8, big, ARRAY_SIZE(big));
ok(ret == ERANGE || ret == EINVAL, "expected ERANGE/EINVAL got %d\n", ret);
ok(dest[0] == 0, "dest[0] not 0\n");
dest[0] = 'A';
ret = p_strncpy_s(dest, 5, big, -1);
ok(ret == STRUNCATE, "expected STRUNCATE got %d\n", ret);
ok(dest[4] == 0, "dest[4] not 0\n");
ok(!memcmp(dest, big, 4), "dest = %s\n", wine_dbgstr_a(dest));
ret = p_strncpy_s(NULL, 0, (void*)0xdeadbeef, 0);
ok(ret == 0, "ret = %d\n", ret);
dest[0] = '1';
dest[1] = 0;
ret = p_strncpy_s(dest+1, 4, dest, -1);
ok(ret == STRUNCATE, "expected ERROR_SUCCESS got %d\n", ret);
ok(dest[0]=='1' && dest[1]=='1' && dest[2]=='1' && dest[3]=='1',
"dest = %s\n", wine_dbgstr_a(dest));
} }
#define okchars(dst, b0, b1, b2, b3, b4, b5, b6, b7) \ #define okchars(dst, b0, b1, b2, b3, b4, b5, b6, b7) \
...@@ -4498,6 +4548,7 @@ START_TEST(string) ...@@ -4498,6 +4548,7 @@ START_TEST(string)
SET(p_strncmp, "strncmp"); SET(p_strncmp, "strncmp");
pstrcpy_s = (void *)GetProcAddress( hMsvcrt,"strcpy_s" ); pstrcpy_s = (void *)GetProcAddress( hMsvcrt,"strcpy_s" );
pstrcat_s = (void *)GetProcAddress( hMsvcrt,"strcat_s" ); pstrcat_s = (void *)GetProcAddress( hMsvcrt,"strcat_s" );
p_strncpy_s = (void *)GetProcAddress( hMsvcrt, "strncpy_s" );
p_mbscat_s = (void*)GetProcAddress( hMsvcrt, "_mbscat_s" ); p_mbscat_s = (void*)GetProcAddress( hMsvcrt, "_mbscat_s" );
p_mbsnbcat_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcat_s" ); p_mbsnbcat_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcat_s" );
p_mbsnbcpy_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcpy_s" ); p_mbsnbcpy_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcpy_s" );
......
...@@ -2376,41 +2376,41 @@ wchar_t* __cdecl wcsncpy( wchar_t* s1, const wchar_t *s2, size_t n ) ...@@ -2376,41 +2376,41 @@ wchar_t* __cdecl wcsncpy( wchar_t* s1, const wchar_t *s2, size_t n )
/****************************************************************** /******************************************************************
* wcsncpy_s (MSVCRT.@) * wcsncpy_s (MSVCRT.@)
*/ */
INT CDECL wcsncpy_s( wchar_t* wcDest, size_t numElement, const wchar_t *wcSrc, INT CDECL wcsncpy_s( wchar_t *dst, size_t elem, const wchar_t *src, size_t count )
size_t count )
{ {
WCHAR *p = wcDest; WCHAR *p = dst;
BOOL truncate = (count == _TRUNCATE); BOOL truncate = (count == _TRUNCATE);
if(!wcDest && !numElement && !count) if (!count)
{
if (dst && elem) *dst = 0;
return 0; return 0;
}
if (!wcDest || !numElement) if (!MSVCRT_CHECK_PMT(dst != NULL)) return EINVAL;
return EINVAL; if (!MSVCRT_CHECK_PMT(elem != 0)) return EINVAL;
if (!MSVCRT_CHECK_PMT(src != NULL))
if (!wcSrc)
{ {
*wcDest = 0; *dst = 0;
return count ? EINVAL : 0; return EINVAL;
} }
while (numElement && count && *wcSrc) while (elem && count && *src)
{ {
*p++ = *wcSrc++; *p++ = *src++;
numElement--; elem--;
count--; count--;
} }
if (!numElement && truncate) if (!elem && truncate)
{ {
*(p-1) = 0; *(p-1) = 0;
return STRUNCATE; return STRUNCATE;
} }
else if (!numElement) else if (!elem)
{ {
*wcDest = 0; *dst = 0;
return ERANGE; return ERANGE;
} }
*p = 0; *p = 0;
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment