1 /*
2 * PROJECT: ReactOS API tests
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Test for RtlUnicodeStringToCountedOemString
5 * COPYRIGHT: Copyright 2021 Jérôme Gardou <jerome.gardou@reactos.org>
6 */
7
8 #include "precomp.h"
9
10 static const struct
11 {
12 ULONG AnsiCp;
13 ULONG OemCp;
14 const UNICODE_STRING StrU;
15 NTSTATUS Status;
16 const OEM_STRING StrOem;
17 } TestData[] =
18 {
19 {
20 1252, 932, /* Western SBCS - Modified SJIS */
21 RTL_CONSTANT_STRING(L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7"),
22 STATUS_BUFFER_OVERFLOW,
23 RTL_CONSTANT_STRING("\x83\x66\x83\x58\x83\x4e")
24 },
25 {
26 932, 1252, /* Modified SJIS - Western SBCS */
27 RTL_CONSTANT_STRING(L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7"),
28 STATUS_UNMAPPABLE_CHARACTER,
29 RTL_CONSTANT_STRING("??????")
30 },
31 {
32 932, 932, /* Modified SJIS - Modified SJIS */
33 RTL_CONSTANT_STRING(L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7"),
34 STATUS_SUCCESS,
35 RTL_CONSTANT_STRING("\x83\x66\x83\x58\x83\x4e\x83\x67\x83\x62\x83\x76")
36 },
37 {
38 1252, 1252, /* Western SBCS */
39 RTL_CONSTANT_STRING(L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7"), /* Some japanese characters */
40 STATUS_UNMAPPABLE_CHARACTER,
41 RTL_CONSTANT_STRING("??????")
42 },
43 };
44
START_TEST(RtlUnicodeStringToCountedOemString)45 START_TEST(RtlUnicodeStringToCountedOemString)
46 {
47 WCHAR BufferU[10];
48 CHAR BufferOem[10];
49 UNICODE_STRING StringU;
50 OEM_STRING StringOem;
51 NTSTATUS Status;
52 int i;
53
54 memset(BufferU, 0xAA, sizeof(BufferU));
55 memset(BufferOem, 0xAA, sizeof(BufferOem));
56
57 BufferU[0] = L'A';
58 BufferU[1] = UNICODE_NULL;
59
60 StringU.Buffer = BufferU;
61 StringU.MaximumLength = 10 * sizeof(WCHAR);
62
63 RtlInitUnicodeString(&StringU, BufferU);
64 ok(StringU.Length == 1 * sizeof(WCHAR), "Invalid size: %d\n", StringU.Length);
65 ok(StringU.MaximumLength == 2 * sizeof(WCHAR), "Invalid size: %d\n", StringU.MaximumLength);
66 ok(StringU.Buffer == BufferU, "Invalid buffer: %p\n", StringU.Buffer);
67
68 StringOem.Buffer = BufferOem;
69 StringOem.Length = 0;
70 StringOem.MaximumLength = 10 * sizeof(CHAR);
71
72 Status = RtlUnicodeStringToCountedOemString(&StringOem, &StringU, FALSE);
73 ok(NT_SUCCESS(Status), "RtlUnicodeStringToCountedOemString failed: %lx\n", Status);
74 ok(StringOem.Length == 1 * sizeof(CHAR), "Invalid size: %d\n", StringOem.Length);
75 ok(StringOem.MaximumLength == 10 * sizeof(CHAR), "Invalid size: %d\n", StringOem.MaximumLength);
76 ok(StringOem.Buffer == BufferOem, "Invalid buffer: %p\n", StringOem.Buffer);
77
78 ok(BufferOem[0] == 'A', "Unexpected first char 0x%02x for OEM string.\n", BufferOem[0]);
79 for (i = 1; i < 10; ++i)
80 {
81 ok(BufferOem[i] == (CHAR)0xAA, "Unexpected char 0x%02x at position %d.\n", BufferOem[i], i);
82 }
83
84 ok(i == 10, "String was not null terminated!\n");
85
86 /* Test buffer overflow */
87 wcsncpy(BufferU, L"Test", _countof(BufferU));
88 RtlInitUnicodeString(&StringU, BufferU);
89 StringU.MaximumLength = sizeof(BufferU);
90 StringOem.Buffer = BufferOem;
91 StringOem.MaximumLength = 1 * sizeof(CHAR);
92 StringOem.Length = 0;
93 memset(BufferOem, 0xAA, sizeof(BufferOem));
94
95 Status = RtlUnicodeStringToCountedOemString(&StringOem, &StringU, FALSE);
96 ok_ntstatus(Status, STATUS_BUFFER_OVERFLOW);
97 ok(StringOem.Length == 4 * sizeof(CHAR), "Invalid size: %d\n", StringOem.Length);
98 ok(StringOem.MaximumLength == 1 * sizeof(CHAR), "Invalid size: %d\n", StringOem.MaximumLength);
99 ok(StringOem.Buffer == BufferOem, "Invalid buffer: %p\n", StringOem.Buffer);
100
101 for (i = 0; i < 10; ++i)
102 {
103 ok(BufferOem[i] == (CHAR)0xAA, "Unexpected char 0x%02x at position %d.\n", BufferOem[i], i);
104 }
105
106 for (i = 0; i < _countof(TestData); i++)
107 {
108 SetupLocale(TestData[i].AnsiCp, TestData[i].OemCp, -1);
109
110 trace("Testing locale %u. ANSI: %u, OEM %u\n", i, (UINT)TestData[i].AnsiCp, (UINT)TestData[i].OemCp);
111
112 /* Get the right length */
113 StringOem.Buffer = NULL;
114 StringOem.Length = 0;
115 StringOem.MaximumLength = 0;
116
117 Status = RtlUnicodeStringToCountedOemString(&StringOem, &TestData[i].StrU, FALSE);
118 ok_ntstatus(Status, STATUS_BUFFER_OVERFLOW);
119 ok_long(StringOem.Length, TestData[i].StrOem.Length);
120 ok_long(StringOem.MaximumLength, 0);
121
122 StringOem.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, StringOem.Length);
123 StringOem.MaximumLength = StringOem.Length;
124 StringOem.Length = 0;
125
126 Status = RtlUnicodeStringToCountedOemString(&StringOem, &TestData[i].StrU, FALSE);
127 ok_ntstatus(Status, TestData[i].Status);
128
129 ok_long(StringOem.Length, TestData[i].StrOem.Length);
130 ok_long(StringOem.MaximumLength, TestData[i].StrOem.Length); /* Untouched */
131 ok_long(memcmp(StringOem.Buffer, TestData[i].StrOem.Buffer, min(StringOem.Length, TestData[i].StrOem.Length)), 0);
132
133 RtlFreeHeap(RtlGetProcessHeap(), 0, StringOem.Buffer);
134 }
135 }
136
137