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
Test_RtlUnicodeStringPrintf()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
Test_RtlUnicodeStringPrintfEx()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
START_TEST(RtlStrSafe)181 START_TEST(RtlStrSafe)
182 {
183 Test_RtlUnicodeStringPrintf();
184 Test_RtlUnicodeStringPrintfEx();
185 }
186