From c8681feee94bf0e31dfb3f065fef432fa4eb39b6 Mon Sep 17 00:00:00 2001 From: Colin Finck Date: Wed, 28 Aug 2019 22:42:52 +0200 Subject: [PATCH] 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) --- modules/rostests/kmtests/rtl/RtlStrSafe.c | 238 +++++++++++----------- sdk/include/ddk/ntstrsafe.h | 112 ++++------ 2 files changed, 159 insertions(+), 191 deletions(-) diff --git a/modules/rostests/kmtests/rtl/RtlStrSafe.c b/modules/rostests/kmtests/rtl/RtlStrSafe.c index 807a036b2a7..82c2fe512cc 100644 --- a/modules/rostests/kmtests/rtl/RtlStrSafe.c +++ b/modules/rostests/kmtests/rtl/RtlStrSafe.c @@ -1,8 +1,9 @@ /* * 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 * COPYRIGHT: Copyright 2018 Hernán Di Pietro + * Copyright 2019 Colin Finck */ #define KMT_EMULATE_KERNEL @@ -13,163 +14,168 @@ #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 Test_RtlUnicodeStringPrintf() { - WCHAR Buffer[1024]; - WCHAR OvrBuffer[1024]; - WCHAR BufferSmall[2]; - WCHAR BufferSmall2[7]; + NTSTATUS Status; + PWSTR pBuffer = NULL; + size_t BufferSize; + size_t EqualBytes; 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) */ - - RtlFillMemory(Buffer, sizeof(Buffer), 0xAA); - RtlFillMemory(BufferSmall, sizeof(BufferSmall), 0xAA); - RtlFillMemory(BufferSmall2, sizeof(BufferSmall2), 0xAA); + KmtStartSeh(); /* STATUS_SUCCESS test */ + BufferSize = 6 * sizeof(WCHAR); + pBuffer = KmtAllocateGuarded(BufferSize); + if (!pBuffer) + goto Cleanup; - UsString.Buffer = Buffer; - UsString.Length = 0; - UsString.MaximumLength = sizeof(Buffer); + RtlFillMemory(pBuffer, BufferSize, 0xAA); + RtlInitEmptyUnicodeString(&UsString, pBuffer, BufferSize); + + 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 */ + BufferSize = 2 * sizeof(WCHAR); + pBuffer = KmtAllocateGuarded(BufferSize); + if (!pBuffer) + goto Cleanup; - UsString.Buffer = BufferSmall; - UsString.Length = 0; - UsString.MaximumLength = sizeof(BufferSmall); - - ok_eq_hex(RtlUnicodeStringPrintf(&UsString, FormatStringStrs, L"AAA", L"BBB", L"CCC"), STATUS_BUFFER_OVERFLOW); + RtlInitEmptyUnicodeString(&UsString, pBuffer, BufferSize); + + Status = RtlUnicodeStringPrintf(&UsString, FormatStringStrs, L"AAA", L"BBB", L"CCC"); + EqualBytes = RtlCompareMemory(UsString.Buffer, L"AA", BufferSize); + ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW); + ok_eq_size(EqualBytes, BufferSize); 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; - UsString.Length = 0; - UsString.MaximumLength = sizeof(BufferSmall2); + KmtFreeGuarded(pBuffer); + pBuffer = NULL; - 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_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); - ok_eq_hex(RtlUnicodeStringPrintf(&UsString, NULL, L"AAA", L"BBB", L"CCC"), STATUS_INVALID_PARAMETER); + // Note: RtlUnicodeStringPrintf returns STATUS_BUFFER_OVERFLOW here while RtlUnicodeStringPrintfEx returns 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); - RtlFillMemory(OvrBuffer, sizeof(OvrBuffer), 0xAA); - 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)))); + // None of these functions should have crashed. + KmtEndSeh(STATUS_SUCCESS); } TESTAPI Test_RtlUnicodeStringPrintfEx() { - WCHAR Buffer[32]; - WCHAR BufferSmall[8] = { 0 }; - WCHAR OvrBuffer[1024]; - UNICODE_STRING UsString, RemString; - const WCHAR FormatStringInts[] = L"%d %d %d"; - const WCHAR FormatStringStrs[] = L"%s %s %s"; - const WCHAR Result[] = L"1 2 3"; + NTSTATUS Status; + PWSTR pBuffer = NULL; + size_t BufferSize; + size_t EqualBytes; + UNICODE_STRING RemString; + UNICODE_STRING UsString; + WCHAR FillResult[10]; - /* No zeros (Don't assume UNICODE_STRINGS are NULL terminated) */ + RtlFillMemory(FillResult, sizeof(FillResult), 0xAA); - RtlFillMemory(Buffer, sizeof(Buffer), 0xAA); - - UsString.Buffer = Buffer; - UsString.Length = 0; - UsString.MaximumLength = sizeof(Buffer); - - RemString.Buffer = (PWCH)NULL; - RemString.Length = 0; - RemString.MaximumLength = 0; + KmtStartSeh(); /* 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); - - 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); + RtlInitEmptyUnicodeString(&UsString, pBuffer, BufferSize); + RtlInitEmptyUnicodeString(&RemString, NULL, 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.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 */ + BufferSize = 8 * sizeof(WCHAR); + pBuffer = KmtAllocateGuarded(BufferSize); + if (!pBuffer) + goto Cleanup; - UsString.Buffer = BufferSmall; - UsString.Length = 0; - UsString.MaximumLength = sizeof(BufferSmall); + RtlInitEmptyUnicodeString(&UsString, pBuffer, BufferSize); + RtlInitEmptyUnicodeString(&RemString, NULL, 0); - RemString.Buffer = (PWCH)NULL; - RemString.Length = 0; - RemString.MaximumLength = 0; - - ok_eq_hex(RtlUnicodeStringPrintfEx(&UsString, &RemString, 0, FormatStringStrs, L"AAA", L"BBB", L"CCC"), STATUS_BUFFER_OVERFLOW); + Status = RtlUnicodeStringPrintfEx(&UsString, &RemString, 0, FormatStringStrs, L"AAA", L"BBB", L"CCC"); + EqualBytes = RtlCompareMemory(UsString.Buffer, L"AAA BBB ", UsString.Length); + ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW); + ok_eq_size(EqualBytes, UsString.Length); 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 - 1) / sizeof(WCHAR)); - ok_eq_uint(RemString.Length, 0); - ok_eq_uint(RemString.MaximumLength, 2); + ok_eq_pointer(RemString.Buffer, &UsString.Buffer[UsString.Length / sizeof(WCHAR)]); + ok_eq_uint(RemString.Length, 0); + ok_eq_uint(RemString.MaximumLength, 0); - /* 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); - 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)))); + // Note: RtlUnicodeStringPrintf returns STATUS_BUFFER_OVERFLOW here while RtlUnicodeStringPrintfEx returns STATUS_INVALID_PARAMETER! + // Documented on MSDN and verified with the Win10 version of ntstrsafe.h + RtlInitEmptyUnicodeString(&UsString, NULL, 0); + 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) diff --git a/sdk/include/ddk/ntstrsafe.h b/sdk/include/ddk/ntstrsafe.h index fac1a46f723..2780efe76e7 100644 --- a/sdk/include/ddk/ntstrsafe.h +++ b/sdk/include/ddk/ntstrsafe.h @@ -15,20 +15,6 @@ #pragma warning(disable:28719) /* disable banned api usage warning */ #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 NTSTRSAFEVAPI static __inline NTSTATUS __cdecl #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 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 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 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 @@ -1366,6 +1350,7 @@ RtlStringCbPrintfExW( { if (cchDest > 0) *pszDest = L'\0'; + return STATUS_INVALID_PARAMETER; } @@ -2842,6 +2827,29 @@ NTSTRSAFEAPI RtlStringVPrintfWorkerA( 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( STRSAFE_LPWSTR pszDest, size_t cchDest, @@ -2883,19 +2891,6 @@ NTSTRSAFEAPI RtlStringVPrintfWorkerW( 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( STRSAFE_LPSTR pszDest, size_t cchDest, @@ -3068,35 +3063,19 @@ NTSTRSAFEAPI RtlpStringVPrintfExWorkerW( } else { - int iRet; - 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; + size_t cchDestNewLen = 0; - if (dwFlags & STRSAFE_FILL_BEHIND_NULL) - { - memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); - } + Status = RtlpArrayVPrintfWorkerW(pszDest, cchDest, pszFormat, &cchDestNewLen, argList); + pszDestEnd = pszDest + cchDestNewLen; + 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) - *pcchDestNewLen = iRet == -1 ? cchDest : iRet; + *pcchDestNewLen = cchDestNewLen; } } } @@ -3120,6 +3099,7 @@ NTSTRSAFEAPI RtlpStringVPrintfExWorkerW( *pszDestEnd = L'\0'; } } + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) { if (cchDest > 0) @@ -3157,24 +3137,6 @@ NTSTRSAFEAPI RtlStringVPrintfExWorkerW( 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 RtlStringLengthWorkerA( _In_reads_or_z_(cchMax) STRSAFE_LPCSTR psz, @@ -3285,7 +3247,7 @@ RtlUnicodeStringPrintf( size_t cchFinalLength; va_list argList; - if (DestinationString == NULL || pszFormat == NULL || DestinationString->Buffer == NULL) + if (DestinationString == NULL || pszFormat == NULL) { Status = STATUS_INVALID_PARAMETER; } @@ -3296,7 +3258,7 @@ RtlUnicodeStringPrintf( { va_start(argList, pszFormat); - Status = RtlStringVPrintfWorkerLenW(DestinationString->Buffer, + Status = RtlpArrayVPrintfWorkerW(DestinationString->Buffer, DestinationString->MaximumLength / sizeof(WCHAR), pszFormat, &cchFinalLength, @@ -3328,7 +3290,7 @@ RtlUnicodeStringPrintfEx( va_start(argList, pszFormat); - Status = RtlStringVPrintfExWorkerLenW(DestinationString->Buffer, + Status = RtlpStringVPrintfExWorkerW(DestinationString->Buffer, DestinationString->MaximumLength / sizeof(WCHAR), DestinationString->MaximumLength, &RemainingString->Buffer,