1 /* 2 * PROJECT: ReactOS kernel-mode tests 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Test for ntstrsafe.h functions 5 * COPYRIGHT: Copyright 2018 Hern�n Di Pietro <hernan.di.pietro@gmail.com> 6 * Copyright 2019 Colin Finck <colin@reactos.org> 7 */ 8 9 #define KMT_EMULATE_KERNEL 10 #include <kmt_test.h> 11 #include <ntstrsafe.h> 12 #include <ntdef.h> 13 #include <ndk/rtlfuncs.h> 14 15 #define TESTAPI static void 16 17 static const WCHAR FormatStringInts[] = L"%d %d %d"; 18 static const WCHAR FormatStringIntsResult[] = L"1 2 3"; 19 static const WCHAR FormatStringStrs[] = L"%s %s %s"; 20 21 22 TESTAPI 23 Test_RtlUnicodeStringPrintf() 24 { 25 NTSTATUS Status; 26 PWSTR pBuffer = NULL; 27 USHORT BufferSize; 28 size_t EqualBytes; 29 UNICODE_STRING UsString; 30 31 KmtStartSeh(); 32 33 /* STATUS_SUCCESS test */ 34 BufferSize = 6 * sizeof(WCHAR); 35 pBuffer = KmtAllocateGuarded(BufferSize); 36 if (!pBuffer) 37 goto Cleanup; 38 39 RtlFillMemory(pBuffer, BufferSize, 0xAA); 40 RtlInitEmptyUnicodeString(&UsString, pBuffer, BufferSize); 41 42 Status = RtlUnicodeStringPrintf(&UsString, FormatStringInts, 1, 2, 3); 43 EqualBytes = RtlCompareMemory(UsString.Buffer, FormatStringIntsResult, sizeof(FormatStringIntsResult)); 44 ok_eq_hex(Status, STATUS_SUCCESS); 45 ok_eq_size(EqualBytes, sizeof(FormatStringIntsResult)); 46 ok_eq_uint(UsString.Length, sizeof(FormatStringIntsResult) - sizeof(WCHAR)); 47 ok_eq_uint(UsString.MaximumLength, BufferSize); 48 49 KmtFreeGuarded(pBuffer); 50 pBuffer = NULL; 51 52 /* STATUS_BUFFER_OVERFLOW tests */ 53 BufferSize = 2 * sizeof(WCHAR); 54 pBuffer = KmtAllocateGuarded(BufferSize); 55 if (!pBuffer) 56 goto Cleanup; 57 58 RtlInitEmptyUnicodeString(&UsString, pBuffer, BufferSize); 59 60 Status = RtlUnicodeStringPrintf(&UsString, FormatStringStrs, L"AAA", L"BBB", L"CCC"); 61 EqualBytes = RtlCompareMemory(UsString.Buffer, L"AA", BufferSize); 62 ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW); 63 ok_eq_size(EqualBytes, BufferSize); 64 ok_eq_uint(UsString.Length, UsString.MaximumLength); 65 66 KmtFreeGuarded(pBuffer); 67 pBuffer = NULL; 68 69 70 BufferSize = 7 * sizeof(WCHAR); 71 pBuffer = KmtAllocateGuarded(BufferSize); 72 if (!pBuffer) 73 goto Cleanup; 74 75 RtlInitEmptyUnicodeString(&UsString, pBuffer, BufferSize); 76 77 Status = RtlUnicodeStringPrintf(&UsString, FormatStringStrs, L"0123", L"4567", L"89AB"); 78 EqualBytes = RtlCompareMemory(UsString.Buffer, L"0123 45", BufferSize); 79 ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW); 80 ok_eq_size(EqualBytes, BufferSize); 81 ok_eq_uint(UsString.Length, UsString.MaximumLength); 82 83 KmtFreeGuarded(pBuffer); 84 pBuffer = NULL; 85 86 // Note: RtlUnicodeStringPrintf returns STATUS_BUFFER_OVERFLOW here while RtlUnicodeStringPrintfEx returns STATUS_INVALID_PARAMETER! 87 // Documented on MSDN and verified with the Win10 version of ntstrsafe.h 88 RtlInitEmptyUnicodeString(&UsString, NULL, 0); 89 Status = RtlUnicodeStringPrintf(&UsString, FormatStringStrs, L"AAA", L"BBB", L"CCC"); 90 ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW); 91 92 93 Cleanup: 94 if (pBuffer) 95 KmtFreeGuarded(pBuffer); 96 97 // None of these functions should have crashed. 98 KmtEndSeh(STATUS_SUCCESS); 99 } 100 101 TESTAPI 102 Test_RtlUnicodeStringPrintfEx() 103 { 104 NTSTATUS Status; 105 PWSTR pBuffer = NULL; 106 USHORT BufferSize; 107 size_t EqualBytes; 108 UNICODE_STRING RemString; 109 UNICODE_STRING UsString; 110 WCHAR FillResult[10]; 111 112 RtlFillMemory(FillResult, sizeof(FillResult), 0xAA); 113 114 KmtStartSeh(); 115 116 /* STATUS_SUCCESS test, fill behind flag: low-byte as fill character */ 117 BufferSize = sizeof(FormatStringIntsResult) - sizeof(UNICODE_NULL) + sizeof(FillResult); 118 pBuffer = KmtAllocateGuarded(BufferSize); 119 if (!pBuffer) 120 goto Cleanup; 121 122 RtlInitEmptyUnicodeString(&UsString, pBuffer, BufferSize); 123 RtlInitEmptyUnicodeString(&RemString, NULL, 0); 124 125 Status = RtlUnicodeStringPrintfEx(&UsString, &RemString, STRSAFE_FILL_BEHIND | 0xAA, FormatStringInts, 1, 2, 3); 126 EqualBytes = RtlCompareMemory(UsString.Buffer, FormatStringIntsResult, sizeof(FormatStringIntsResult) - sizeof(WCHAR)); 127 ok_eq_hex(Status, STATUS_SUCCESS); 128 ok_eq_size(EqualBytes, sizeof(FormatStringIntsResult) - sizeof(WCHAR)); 129 ok_eq_uint(UsString.Length, sizeof(FormatStringIntsResult) - sizeof(WCHAR)); 130 ok_eq_uint(UsString.MaximumLength, BufferSize); 131 132 ok_eq_pointer(RemString.Buffer, &UsString.Buffer[UsString.Length / sizeof(WCHAR)]); 133 ok_eq_uint(RemString.Length, 0); 134 ok_eq_uint(RemString.MaximumLength, UsString.MaximumLength - UsString.Length); 135 136 EqualBytes = RtlCompareMemory(RemString.Buffer, FillResult, RemString.MaximumLength); 137 ok_eq_size(EqualBytes, sizeof(FillResult)); 138 139 KmtFreeGuarded(pBuffer); 140 pBuffer = NULL; 141 142 143 /* STATUS_BUFFER_OVERFLOW test */ 144 BufferSize = 8 * sizeof(WCHAR); 145 pBuffer = KmtAllocateGuarded(BufferSize); 146 if (!pBuffer) 147 goto Cleanup; 148 149 RtlInitEmptyUnicodeString(&UsString, pBuffer, BufferSize); 150 RtlInitEmptyUnicodeString(&RemString, NULL, 0); 151 152 Status = RtlUnicodeStringPrintfEx(&UsString, &RemString, 0, FormatStringStrs, L"AAA", L"BBB", L"CCC"); 153 EqualBytes = RtlCompareMemory(UsString.Buffer, L"AAA BBB ", UsString.Length); 154 ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW); 155 ok_eq_size(EqualBytes, UsString.Length); 156 ok_eq_uint(UsString.Length, UsString.MaximumLength); 157 158 ok_eq_pointer(RemString.Buffer, &UsString.Buffer[UsString.Length / sizeof(WCHAR)]); 159 ok_eq_uint(RemString.Length, 0); 160 ok_eq_uint(RemString.MaximumLength, 0); 161 162 KmtFreeGuarded(pBuffer); 163 pBuffer = NULL; 164 165 166 // Note: RtlUnicodeStringPrintf returns STATUS_BUFFER_OVERFLOW here while RtlUnicodeStringPrintfEx returns STATUS_INVALID_PARAMETER! 167 // Documented on MSDN and verified with the Win10 version of ntstrsafe.h 168 RtlInitEmptyUnicodeString(&UsString, NULL, 0); 169 Status = RtlUnicodeStringPrintfEx(&UsString, NULL, 0, FormatStringStrs, L"AAA", L"BBB", L"CCC"); 170 ok_eq_hex(Status, STATUS_INVALID_PARAMETER); 171 172 173 Cleanup: 174 if (pBuffer) 175 KmtFreeGuarded(pBuffer); 176 177 // None of these functions should have crashed. 178 KmtEndSeh(STATUS_SUCCESS); 179 } 180 181 START_TEST(RtlStrSafe) 182 { 183 Test_RtlUnicodeStringPrintf(); 184 Test_RtlUnicodeStringPrintfEx(); 185 } 186