mirror of
https://github.com/reactos/reactos.git
synced 2025-05-18 16:51:18 +00:00
Fix the ntstrsafe.h tests to make sense, actually succeed using ntstrsafe.h from Win10 (10.0.15063), and fix ReactOS' ntstrsafe.h to also pass these tests. (#1859)
This commit is contained in:
parent
46ed46c73f
commit
c8681feee9
2 changed files with 159 additions and 191 deletions
|
@ -1,8 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS kernel-mode tests
|
* PROJECT: ReactOS kernel-mode tests
|
||||||
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: Test for ntstrsafe.h functions
|
* PURPOSE: Test for ntstrsafe.h functions
|
||||||
* COPYRIGHT: Copyright 2018 Hernán Di Pietro <hernan.di.pietro@gmail.com>
|
* COPYRIGHT: Copyright 2018 Hernán Di Pietro <hernan.di.pietro@gmail.com>
|
||||||
|
* Copyright 2019 Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define KMT_EMULATE_KERNEL
|
#define KMT_EMULATE_KERNEL
|
||||||
|
@ -13,163 +14,168 @@
|
||||||
|
|
||||||
#define TESTAPI static void
|
#define TESTAPI static void
|
||||||
|
|
||||||
|
static const WCHAR FormatStringInts[] = L"%d %d %d";
|
||||||
|
static const WCHAR FormatStringIntsResult[] = L"1 2 3";
|
||||||
|
static const WCHAR FormatStringStrs[] = L"%s %s %s";
|
||||||
|
|
||||||
|
|
||||||
TESTAPI
|
TESTAPI
|
||||||
Test_RtlUnicodeStringPrintf()
|
Test_RtlUnicodeStringPrintf()
|
||||||
{
|
{
|
||||||
WCHAR Buffer[1024];
|
NTSTATUS Status;
|
||||||
WCHAR OvrBuffer[1024];
|
PWSTR pBuffer = NULL;
|
||||||
WCHAR BufferSmall[2];
|
size_t BufferSize;
|
||||||
WCHAR BufferSmall2[7];
|
size_t EqualBytes;
|
||||||
UNICODE_STRING UsString;
|
UNICODE_STRING UsString;
|
||||||
const WCHAR FormatStringInts[] = L"%d %d %d";
|
|
||||||
const WCHAR FormatStringStrs[] = L"%s %s %s";
|
|
||||||
const WCHAR Result[] = L"1 2 3";
|
|
||||||
UNICODE_STRING UsStringNull;
|
|
||||||
|
|
||||||
/* No zeros (Don't assume UNICODE_STRINGS are NULL terminated) */
|
KmtStartSeh();
|
||||||
|
|
||||||
RtlFillMemory(Buffer, sizeof(Buffer), 0xAA);
|
|
||||||
RtlFillMemory(BufferSmall, sizeof(BufferSmall), 0xAA);
|
|
||||||
RtlFillMemory(BufferSmall2, sizeof(BufferSmall2), 0xAA);
|
|
||||||
|
|
||||||
/* STATUS_SUCCESS test */
|
/* STATUS_SUCCESS test */
|
||||||
|
BufferSize = 6 * sizeof(WCHAR);
|
||||||
|
pBuffer = KmtAllocateGuarded(BufferSize);
|
||||||
|
if (!pBuffer)
|
||||||
|
goto Cleanup;
|
||||||
|
|
||||||
UsString.Buffer = Buffer;
|
RtlFillMemory(pBuffer, BufferSize, 0xAA);
|
||||||
UsString.Length = 0;
|
RtlInitEmptyUnicodeString(&UsString, pBuffer, BufferSize);
|
||||||
UsString.MaximumLength = sizeof(Buffer);
|
|
||||||
|
Status = RtlUnicodeStringPrintf(&UsString, FormatStringInts, 1, 2, 3);
|
||||||
|
EqualBytes = RtlCompareMemory(UsString.Buffer, FormatStringIntsResult, sizeof(FormatStringIntsResult));
|
||||||
|
ok_eq_hex(Status, STATUS_SUCCESS);
|
||||||
|
ok_eq_size(EqualBytes, sizeof(FormatStringIntsResult));
|
||||||
|
ok_eq_uint(UsString.Length, sizeof(FormatStringIntsResult) - sizeof(WCHAR));
|
||||||
|
ok_eq_uint(UsString.MaximumLength, BufferSize);
|
||||||
|
|
||||||
|
KmtFreeGuarded(pBuffer);
|
||||||
|
pBuffer = NULL;
|
||||||
|
|
||||||
ok_eq_hex(RtlUnicodeStringPrintf(&UsString, FormatStringInts, 1, 2, 3), STATUS_SUCCESS);
|
|
||||||
ok_eq_uint(UsString.Length, sizeof(Result) - sizeof(WCHAR));
|
|
||||||
ok_eq_uint(UsString.MaximumLength, sizeof(Buffer));
|
|
||||||
ok_eq_wchar(UsString.Buffer[0], L'1');
|
|
||||||
ok_eq_wchar(UsString.Buffer[1], L' ');
|
|
||||||
ok_eq_wchar(UsString.Buffer[2], L'2');
|
|
||||||
ok_eq_wchar(UsString.Buffer[3], L' ');
|
|
||||||
ok_eq_wchar(UsString.Buffer[4], L'3');
|
|
||||||
ok_eq_wchar(UsString.Buffer[5], (WCHAR) 0);
|
|
||||||
|
|
||||||
/* STATUS_BUFFER_OVERFLOW tests */
|
/* STATUS_BUFFER_OVERFLOW tests */
|
||||||
|
BufferSize = 2 * sizeof(WCHAR);
|
||||||
|
pBuffer = KmtAllocateGuarded(BufferSize);
|
||||||
|
if (!pBuffer)
|
||||||
|
goto Cleanup;
|
||||||
|
|
||||||
UsString.Buffer = BufferSmall;
|
RtlInitEmptyUnicodeString(&UsString, pBuffer, BufferSize);
|
||||||
UsString.Length = 0;
|
|
||||||
UsString.MaximumLength = sizeof(BufferSmall);
|
Status = RtlUnicodeStringPrintf(&UsString, FormatStringStrs, L"AAA", L"BBB", L"CCC");
|
||||||
|
EqualBytes = RtlCompareMemory(UsString.Buffer, L"AA", BufferSize);
|
||||||
ok_eq_hex(RtlUnicodeStringPrintf(&UsString, FormatStringStrs, L"AAA", L"BBB", L"CCC"), STATUS_BUFFER_OVERFLOW);
|
ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW);
|
||||||
|
ok_eq_size(EqualBytes, BufferSize);
|
||||||
ok_eq_uint(UsString.Length, UsString.MaximumLength);
|
ok_eq_uint(UsString.Length, UsString.MaximumLength);
|
||||||
ok_eq_char(UsString.Buffer[0], L'A');
|
|
||||||
ok_eq_char(UsString.Buffer[1], (WCHAR)0);
|
|
||||||
|
|
||||||
UsString.Buffer = BufferSmall2;
|
KmtFreeGuarded(pBuffer);
|
||||||
UsString.Length = 0;
|
pBuffer = NULL;
|
||||||
UsString.MaximumLength = sizeof(BufferSmall2);
|
|
||||||
|
|
||||||
ok_eq_hex(RtlUnicodeStringPrintf(&UsString, FormatStringStrs, L"0123", L"4567", L"89AB"), STATUS_BUFFER_OVERFLOW);
|
|
||||||
|
BufferSize = 7 * sizeof(WCHAR);
|
||||||
|
pBuffer = KmtAllocateGuarded(BufferSize);
|
||||||
|
if (!pBuffer)
|
||||||
|
goto Cleanup;
|
||||||
|
|
||||||
|
RtlInitEmptyUnicodeString(&UsString, pBuffer, BufferSize);
|
||||||
|
|
||||||
|
Status = RtlUnicodeStringPrintf(&UsString, FormatStringStrs, L"0123", L"4567", L"89AB");
|
||||||
|
EqualBytes = RtlCompareMemory(UsString.Buffer, L"0123 45", BufferSize);
|
||||||
|
ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW);
|
||||||
|
ok_eq_size(EqualBytes, BufferSize);
|
||||||
ok_eq_uint(UsString.Length, UsString.MaximumLength);
|
ok_eq_uint(UsString.Length, UsString.MaximumLength);
|
||||||
ok_eq_char(UsString.Buffer[0], L'0');
|
|
||||||
ok_eq_char(UsString.Buffer[1], L'1');
|
|
||||||
ok_eq_char(UsString.Buffer[2], L'2');
|
|
||||||
ok_eq_char(UsString.Buffer[3], L'3');
|
|
||||||
ok_eq_char(UsString.Buffer[4], L' ');
|
|
||||||
ok_eq_char(UsString.Buffer[5], L'4');
|
|
||||||
ok_eq_char(UsString.Buffer[6], (WCHAR) 0);
|
|
||||||
|
|
||||||
///* STATUS_INVALID_PARAMETER tests */
|
KmtFreeGuarded(pBuffer);
|
||||||
|
pBuffer = NULL;
|
||||||
|
|
||||||
ok_eq_hex(RtlUnicodeStringPrintf(NULL, FormatStringStrs, L"AAA", L"BBB", L"CCC"), STATUS_INVALID_PARAMETER);
|
// Note: RtlUnicodeStringPrintf returns STATUS_BUFFER_OVERFLOW here while RtlUnicodeStringPrintfEx returns STATUS_INVALID_PARAMETER!
|
||||||
ok_eq_hex(RtlUnicodeStringPrintf(&UsString, NULL, L"AAA", L"BBB", L"CCC"), STATUS_INVALID_PARAMETER);
|
// Documented on MSDN and verified with the Win10 version of ntstrsafe.h
|
||||||
|
RtlInitEmptyUnicodeString(&UsString, NULL, 0);
|
||||||
|
Status = RtlUnicodeStringPrintf(&UsString, FormatStringStrs, L"AAA", L"BBB", L"CCC");
|
||||||
|
ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
UsStringNull.Buffer = (PWCH)NULL;
|
|
||||||
UsStringNull.Length = 0;
|
|
||||||
UsStringNull.MaximumLength = 0;
|
|
||||||
ok_eq_bool(RtlUnicodeStringPrintf(&UsStringNull, FormatStringStrs, L"AAA", L"BBB", L"CCC"), STATUS_INVALID_PARAMETER);
|
|
||||||
|
|
||||||
/* Test for buffer overruns */
|
Cleanup:
|
||||||
|
if (pBuffer)
|
||||||
|
KmtFreeGuarded(pBuffer);
|
||||||
|
|
||||||
RtlFillMemory(Buffer, sizeof(Buffer), 0xAA);
|
// None of these functions should have crashed.
|
||||||
RtlFillMemory(OvrBuffer, sizeof(OvrBuffer), 0xAA);
|
KmtEndSeh(STATUS_SUCCESS);
|
||||||
UsString.Buffer = Buffer;
|
|
||||||
UsString.Length = 0;
|
|
||||||
UsString.MaximumLength = 16 * sizeof(WCHAR);
|
|
||||||
|
|
||||||
ok_eq_hex(RtlUnicodeStringPrintf(&UsString, FormatStringStrs, L"abc", L"def", L"ghi"), STATUS_SUCCESS);
|
|
||||||
ok_eq_uint(UsString.Length, sizeof(L"abc def ghi") -sizeof(WCHAR));
|
|
||||||
ok_eq_char(UsString.Buffer[11], (WCHAR)0);
|
|
||||||
ok_eq_uint(0, memcmp(OvrBuffer + 12, Buffer + 12, sizeof(Buffer) - (12 * sizeof(WCHAR))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TESTAPI
|
TESTAPI
|
||||||
Test_RtlUnicodeStringPrintfEx()
|
Test_RtlUnicodeStringPrintfEx()
|
||||||
{
|
{
|
||||||
WCHAR Buffer[32];
|
NTSTATUS Status;
|
||||||
WCHAR BufferSmall[8] = { 0 };
|
PWSTR pBuffer = NULL;
|
||||||
WCHAR OvrBuffer[1024];
|
size_t BufferSize;
|
||||||
UNICODE_STRING UsString, RemString;
|
size_t EqualBytes;
|
||||||
const WCHAR FormatStringInts[] = L"%d %d %d";
|
UNICODE_STRING RemString;
|
||||||
const WCHAR FormatStringStrs[] = L"%s %s %s";
|
UNICODE_STRING UsString;
|
||||||
const WCHAR Result[] = L"1 2 3";
|
WCHAR FillResult[10];
|
||||||
|
|
||||||
/* No zeros (Don't assume UNICODE_STRINGS are NULL terminated) */
|
RtlFillMemory(FillResult, sizeof(FillResult), 0xAA);
|
||||||
|
|
||||||
RtlFillMemory(Buffer, sizeof(Buffer), 0xAA);
|
KmtStartSeh();
|
||||||
|
|
||||||
UsString.Buffer = Buffer;
|
|
||||||
UsString.Length = 0;
|
|
||||||
UsString.MaximumLength = sizeof(Buffer);
|
|
||||||
|
|
||||||
RemString.Buffer = (PWCH)NULL;
|
|
||||||
RemString.Length = 0;
|
|
||||||
RemString.MaximumLength = 0;
|
|
||||||
|
|
||||||
/* STATUS_SUCCESS test, fill behind flag: low-byte as fill character */
|
/* STATUS_SUCCESS test, fill behind flag: low-byte as fill character */
|
||||||
|
BufferSize = sizeof(FormatStringIntsResult) - sizeof(UNICODE_NULL) + sizeof(FillResult);
|
||||||
|
pBuffer = KmtAllocateGuarded(BufferSize);
|
||||||
|
if (!pBuffer)
|
||||||
|
goto Cleanup;
|
||||||
|
|
||||||
ok_eq_hex(RtlUnicodeStringPrintfEx(&UsString, &RemString, STRSAFE_FILL_BEHIND | 0xFF, FormatStringInts, 1, 2, 3), STATUS_SUCCESS);
|
RtlInitEmptyUnicodeString(&UsString, pBuffer, BufferSize);
|
||||||
|
RtlInitEmptyUnicodeString(&RemString, NULL, 0);
|
||||||
ok_eq_uint(UsString.Length, sizeof(Result) - sizeof(WCHAR));
|
|
||||||
ok_eq_uint(UsString.MaximumLength, sizeof(Buffer));
|
|
||||||
ok_eq_uint(memcmp(UsString.Buffer, Result, sizeof(Result) - sizeof(WCHAR)), 0);
|
|
||||||
|
|
||||||
ok_eq_pointer(RemString.Buffer, UsString.Buffer + (UsString.Length / sizeof(WCHAR)));
|
Status = RtlUnicodeStringPrintfEx(&UsString, &RemString, STRSAFE_FILL_BEHIND | 0xAA, FormatStringInts, 1, 2, 3);
|
||||||
|
EqualBytes = RtlCompareMemory(UsString.Buffer, FormatStringIntsResult, sizeof(FormatStringIntsResult) - sizeof(WCHAR));
|
||||||
|
ok_eq_hex(Status, STATUS_SUCCESS);
|
||||||
|
ok_eq_size(EqualBytes, sizeof(FormatStringIntsResult) - sizeof(WCHAR));
|
||||||
|
ok_eq_uint(UsString.Length, sizeof(FormatStringIntsResult) - sizeof(WCHAR));
|
||||||
|
ok_eq_uint(UsString.MaximumLength, BufferSize);
|
||||||
|
|
||||||
|
ok_eq_pointer(RemString.Buffer, &UsString.Buffer[UsString.Length / sizeof(WCHAR)]);
|
||||||
ok_eq_uint(RemString.Length, 0);
|
ok_eq_uint(RemString.Length, 0);
|
||||||
ok_eq_uint(RemString.MaximumLength, UsString.MaximumLength - UsString.Length);
|
ok_eq_uint(RemString.MaximumLength, UsString.MaximumLength - UsString.Length);
|
||||||
|
|
||||||
|
EqualBytes = RtlCompareMemory(RemString.Buffer, FillResult, RemString.MaximumLength);
|
||||||
|
ok_eq_size(EqualBytes, sizeof(FillResult));
|
||||||
|
|
||||||
|
KmtFreeGuarded(pBuffer);
|
||||||
|
pBuffer = NULL;
|
||||||
|
|
||||||
|
|
||||||
/* STATUS_BUFFER_OVERFLOW test */
|
/* STATUS_BUFFER_OVERFLOW test */
|
||||||
|
BufferSize = 8 * sizeof(WCHAR);
|
||||||
|
pBuffer = KmtAllocateGuarded(BufferSize);
|
||||||
|
if (!pBuffer)
|
||||||
|
goto Cleanup;
|
||||||
|
|
||||||
UsString.Buffer = BufferSmall;
|
RtlInitEmptyUnicodeString(&UsString, pBuffer, BufferSize);
|
||||||
UsString.Length = 0;
|
RtlInitEmptyUnicodeString(&RemString, NULL, 0);
|
||||||
UsString.MaximumLength = sizeof(BufferSmall);
|
|
||||||
|
|
||||||
RemString.Buffer = (PWCH)NULL;
|
Status = RtlUnicodeStringPrintfEx(&UsString, &RemString, 0, FormatStringStrs, L"AAA", L"BBB", L"CCC");
|
||||||
RemString.Length = 0;
|
EqualBytes = RtlCompareMemory(UsString.Buffer, L"AAA BBB ", UsString.Length);
|
||||||
RemString.MaximumLength = 0;
|
ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW);
|
||||||
|
ok_eq_size(EqualBytes, UsString.Length);
|
||||||
ok_eq_hex(RtlUnicodeStringPrintfEx(&UsString, &RemString, 0, FormatStringStrs, L"AAA", L"BBB", L"CCC"), STATUS_BUFFER_OVERFLOW);
|
|
||||||
ok_eq_uint(UsString.Length, UsString.MaximumLength);
|
ok_eq_uint(UsString.Length, UsString.MaximumLength);
|
||||||
ok_eq_char(UsString.Buffer[0], L'A');
|
|
||||||
ok_eq_char(UsString.Buffer[1], L'A');
|
|
||||||
ok_eq_char(UsString.Buffer[2], L'A');
|
|
||||||
ok_eq_char(UsString.Buffer[3], L' ');
|
|
||||||
ok_eq_char(UsString.Buffer[4], L'B');
|
|
||||||
ok_eq_char(UsString.Buffer[5], L'B');
|
|
||||||
ok_eq_char(UsString.Buffer[6], L'B');
|
|
||||||
ok_eq_char(UsString.Buffer[7], (WCHAR)0);
|
|
||||||
|
|
||||||
// Takes \0 into account
|
ok_eq_pointer(RemString.Buffer, &UsString.Buffer[UsString.Length / sizeof(WCHAR)]);
|
||||||
ok_eq_pointer(RemString.Buffer, UsString.Buffer + (UsString.Length - 1) / sizeof(WCHAR));
|
ok_eq_uint(RemString.Length, 0);
|
||||||
ok_eq_uint(RemString.Length, 0);
|
ok_eq_uint(RemString.MaximumLength, 0);
|
||||||
ok_eq_uint(RemString.MaximumLength, 2);
|
|
||||||
|
|
||||||
/* Test for buffer overruns */
|
KmtFreeGuarded(pBuffer);
|
||||||
|
pBuffer = NULL;
|
||||||
|
|
||||||
RtlFillMemory(Buffer, sizeof(Buffer), 0xAA);
|
|
||||||
RtlFillMemory(OvrBuffer, sizeof(OvrBuffer), 0xAA);
|
|
||||||
UsString.Buffer = Buffer;
|
|
||||||
UsString.Length = 0;
|
|
||||||
UsString.MaximumLength = 16 * sizeof(WCHAR);
|
|
||||||
|
|
||||||
ok_eq_hex(RtlUnicodeStringPrintfEx(&UsString, &RemString, 0, FormatStringStrs, L"abc", L"def", L"ghi"), STATUS_SUCCESS);
|
// Note: RtlUnicodeStringPrintf returns STATUS_BUFFER_OVERFLOW here while RtlUnicodeStringPrintfEx returns STATUS_INVALID_PARAMETER!
|
||||||
ok_eq_uint(UsString.Length, sizeof(L"abc def ghi") - sizeof(WCHAR));
|
// Documented on MSDN and verified with the Win10 version of ntstrsafe.h
|
||||||
ok_eq_char(UsString.Buffer[11], (WCHAR)0);
|
RtlInitEmptyUnicodeString(&UsString, NULL, 0);
|
||||||
ok_eq_uint(0, memcmp(OvrBuffer + 12, Buffer + 12, sizeof(Buffer) - (12 * sizeof(WCHAR))));
|
Status = RtlUnicodeStringPrintfEx(&UsString, NULL, 0, FormatStringStrs, L"AAA", L"BBB", L"CCC");
|
||||||
|
ok_eq_hex(Status, STATUS_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
if (pBuffer)
|
||||||
|
KmtFreeGuarded(pBuffer);
|
||||||
|
|
||||||
|
// None of these functions should have crashed.
|
||||||
|
KmtEndSeh(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(RtlStrSafe)
|
START_TEST(RtlStrSafe)
|
||||||
|
|
|
@ -15,20 +15,6 @@
|
||||||
#pragma warning(disable:28719) /* disable banned api usage warning */
|
#pragma warning(disable:28719) /* disable banned api usage warning */
|
||||||
#endif /* _MSC_VER */
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
#ifndef C_ASSERT
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
# define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
|
|
||||||
#else
|
|
||||||
# define C_ASSERT(e) extern void __C_ASSERT__(int [(e)?1:-1])
|
|
||||||
#endif
|
|
||||||
#endif /* C_ASSERT */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define _STRSAFE_EXTERN_C extern "C"
|
|
||||||
#else
|
|
||||||
#define _STRSAFE_EXTERN_C extern
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define NTSTRSAFEAPI static __inline NTSTATUS NTAPI
|
#define NTSTRSAFEAPI static __inline NTSTATUS NTAPI
|
||||||
#define NTSTRSAFEVAPI static __inline NTSTATUS __cdecl
|
#define NTSTRSAFEVAPI static __inline NTSTATUS __cdecl
|
||||||
#define NTSTRSAFE_INLINE_API static __inline NTSTATUS NTAPI
|
#define NTSTRSAFE_INLINE_API static __inline NTSTATUS NTAPI
|
||||||
|
@ -92,10 +78,8 @@ NTSTRSAFEAPI RtlStringCatNExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_
|
||||||
NTSTRSAFEAPI RtlStringCatNExWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc, size_t cchToAppend, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
|
NTSTRSAFEAPI RtlStringCatNExWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc, size_t cchToAppend, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
|
||||||
NTSTRSAFEAPI RtlStringVPrintfWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszFormat, va_list argList);
|
NTSTRSAFEAPI RtlStringVPrintfWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszFormat, va_list argList);
|
||||||
NTSTRSAFEAPI RtlStringVPrintfWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat, va_list argList);
|
NTSTRSAFEAPI RtlStringVPrintfWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat, va_list argList);
|
||||||
NTSTRSAFEAPI RtlStringVPrintfWorkerLenW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat, size_t* pcchDestNewLen, va_list argList);
|
|
||||||
NTSTRSAFEAPI RtlStringVPrintfExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCSTR pszFormat, va_list argList);
|
NTSTRSAFEAPI RtlStringVPrintfExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCSTR pszFormat, va_list argList);
|
||||||
NTSTRSAFEAPI RtlStringVPrintfExWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCWSTR pszFormat, va_list argList);
|
NTSTRSAFEAPI RtlStringVPrintfExWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCWSTR pszFormat, va_list argList);
|
||||||
NTSTRSAFEAPI RtlStringVPrintfExWorkerLenW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCWSTR pszFormat, size_t* pcchDestNewLen, va_list argList);
|
|
||||||
NTSTRSAFEAPI RtlUnicodeStringValidate(PCUNICODE_STRING SourceString);
|
NTSTRSAFEAPI RtlUnicodeStringValidate(PCUNICODE_STRING SourceString);
|
||||||
|
|
||||||
NTSTRSAFEAPI
|
NTSTRSAFEAPI
|
||||||
|
@ -1366,6 +1350,7 @@ RtlStringCbPrintfExW(
|
||||||
{
|
{
|
||||||
if (cchDest > 0)
|
if (cchDest > 0)
|
||||||
*pszDest = L'\0';
|
*pszDest = L'\0';
|
||||||
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2842,6 +2827,29 @@ NTSTRSAFEAPI RtlStringVPrintfWorkerA(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTRSAFEAPI RtlpArrayVPrintfWorkerW(
|
||||||
|
STRSAFE_LPWSTR pszDest,
|
||||||
|
size_t cchDest,
|
||||||
|
STRSAFE_LPCWSTR pszFormat,
|
||||||
|
size_t* pcchDestNewLen,
|
||||||
|
va_list argList)
|
||||||
|
{
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
int iRet = _vsnwprintf(pszDest, cchDest, pszFormat, argList);
|
||||||
|
|
||||||
|
if ((iRet < 0) || (((size_t)iRet) > cchDest))
|
||||||
|
{
|
||||||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
*pcchDestNewLen = cchDest;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*pcchDestNewLen = iRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTRSAFEAPI RtlpStringVPrintfWorkerW(
|
NTSTRSAFEAPI RtlpStringVPrintfWorkerW(
|
||||||
STRSAFE_LPWSTR pszDest,
|
STRSAFE_LPWSTR pszDest,
|
||||||
size_t cchDest,
|
size_t cchDest,
|
||||||
|
@ -2883,19 +2891,6 @@ NTSTRSAFEAPI RtlStringVPrintfWorkerW(
|
||||||
return RtlpStringVPrintfWorkerW(pszDest, cchDest, pszFormat, NULL, argList);
|
return RtlpStringVPrintfWorkerW(pszDest, cchDest, pszFormat, NULL, argList);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTRSAFEAPI RtlStringVPrintfWorkerLenW(
|
|
||||||
STRSAFE_LPWSTR pszDest,
|
|
||||||
size_t cchDest,
|
|
||||||
STRSAFE_LPCWSTR pszFormat,
|
|
||||||
size_t* pcchDestNewLen,
|
|
||||||
va_list argList)
|
|
||||||
{
|
|
||||||
if (cchDest == 0 || pcchDestNewLen == 0)
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
return RtlpStringVPrintfWorkerW(pszDest, cchDest, pszFormat, pcchDestNewLen, argList);
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTRSAFEAPI RtlStringVPrintfExWorkerA(
|
NTSTRSAFEAPI RtlStringVPrintfExWorkerA(
|
||||||
STRSAFE_LPSTR pszDest,
|
STRSAFE_LPSTR pszDest,
|
||||||
size_t cchDest,
|
size_t cchDest,
|
||||||
|
@ -3068,35 +3063,19 @@ NTSTRSAFEAPI RtlpStringVPrintfExWorkerW(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int iRet;
|
size_t cchDestNewLen = 0;
|
||||||
size_t cchMax = cchDest - 1;
|
|
||||||
iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList);
|
|
||||||
if ((iRet < 0) || (((size_t)iRet) > cchMax))
|
|
||||||
{
|
|
||||||
pszDestEnd = pszDest + cchMax;
|
|
||||||
cchRemaining = 1;
|
|
||||||
*pszDestEnd = L'\0';
|
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
else if (((size_t)iRet) == cchMax)
|
|
||||||
{
|
|
||||||
pszDestEnd = pszDest + cchMax;
|
|
||||||
cchRemaining = 1;
|
|
||||||
*pszDestEnd = L'\0';
|
|
||||||
}
|
|
||||||
else if (((size_t)iRet) < cchMax)
|
|
||||||
{
|
|
||||||
pszDestEnd = pszDest + iRet;
|
|
||||||
cchRemaining = cchDest - iRet;
|
|
||||||
|
|
||||||
if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
|
Status = RtlpArrayVPrintfWorkerW(pszDest, cchDest, pszFormat, &cchDestNewLen, argList);
|
||||||
{
|
pszDestEnd = pszDest + cchDestNewLen;
|
||||||
memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
|
cchRemaining = cchDest - cchDestNewLen;
|
||||||
}
|
|
||||||
|
if (NT_SUCCESS(Status) && (dwFlags & STRSAFE_FILL_BEHIND) && cchRemaining)
|
||||||
|
{
|
||||||
|
memset(pszDestEnd, STRSAFE_GET_FILL_PATTERN(dwFlags), (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcchDestNewLen)
|
if (pcchDestNewLen)
|
||||||
*pcchDestNewLen = iRet == -1 ? cchDest : iRet;
|
*pcchDestNewLen = cchDestNewLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3120,6 +3099,7 @@ NTSTRSAFEAPI RtlpStringVPrintfExWorkerW(
|
||||||
*pszDestEnd = L'\0';
|
*pszDestEnd = L'\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
|
if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
|
||||||
{
|
{
|
||||||
if (cchDest > 0)
|
if (cchDest > 0)
|
||||||
|
@ -3157,24 +3137,6 @@ NTSTRSAFEAPI RtlStringVPrintfExWorkerW(
|
||||||
return RtlpStringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, NULL, argList);
|
return RtlpStringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, NULL, argList);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTRSAFEAPI RtlStringVPrintfExWorkerLenW(
|
|
||||||
STRSAFE_LPWSTR pszDest,
|
|
||||||
size_t cchDest,
|
|
||||||
size_t cbDest,
|
|
||||||
STRSAFE_LPWSTR *ppszDestEnd,
|
|
||||||
size_t *pcchRemaining,
|
|
||||||
STRSAFE_DWORD dwFlags,
|
|
||||||
STRSAFE_LPCWSTR pszFormat,
|
|
||||||
size_t* pcchDestNewLen,
|
|
||||||
va_list argList)
|
|
||||||
{
|
|
||||||
if (pcchDestNewLen == 0)
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
return RtlpStringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, pcchDestNewLen, argList);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NTSTRSAFEAPI
|
NTSTRSAFEAPI
|
||||||
RtlStringLengthWorkerA(
|
RtlStringLengthWorkerA(
|
||||||
_In_reads_or_z_(cchMax) STRSAFE_LPCSTR psz,
|
_In_reads_or_z_(cchMax) STRSAFE_LPCSTR psz,
|
||||||
|
@ -3285,7 +3247,7 @@ RtlUnicodeStringPrintf(
|
||||||
size_t cchFinalLength;
|
size_t cchFinalLength;
|
||||||
va_list argList;
|
va_list argList;
|
||||||
|
|
||||||
if (DestinationString == NULL || pszFormat == NULL || DestinationString->Buffer == NULL)
|
if (DestinationString == NULL || pszFormat == NULL)
|
||||||
{
|
{
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
@ -3296,7 +3258,7 @@ RtlUnicodeStringPrintf(
|
||||||
{
|
{
|
||||||
va_start(argList, pszFormat);
|
va_start(argList, pszFormat);
|
||||||
|
|
||||||
Status = RtlStringVPrintfWorkerLenW(DestinationString->Buffer,
|
Status = RtlpArrayVPrintfWorkerW(DestinationString->Buffer,
|
||||||
DestinationString->MaximumLength / sizeof(WCHAR),
|
DestinationString->MaximumLength / sizeof(WCHAR),
|
||||||
pszFormat,
|
pszFormat,
|
||||||
&cchFinalLength,
|
&cchFinalLength,
|
||||||
|
@ -3328,7 +3290,7 @@ RtlUnicodeStringPrintfEx(
|
||||||
|
|
||||||
va_start(argList, pszFormat);
|
va_start(argList, pszFormat);
|
||||||
|
|
||||||
Status = RtlStringVPrintfExWorkerLenW(DestinationString->Buffer,
|
Status = RtlpStringVPrintfExWorkerW(DestinationString->Buffer,
|
||||||
DestinationString->MaximumLength / sizeof(WCHAR),
|
DestinationString->MaximumLength / sizeof(WCHAR),
|
||||||
DestinationString->MaximumLength,
|
DestinationString->MaximumLength,
|
||||||
&RemainingString->Buffer,
|
&RemainingString->Buffer,
|
||||||
|
|
Loading…
Reference in a new issue