https://git.reactos.org/?p=reactos.git;a=commitdiff;h=53a6c44f74efc7576e47e…
commit 53a6c44f74efc7576e47e7da11bbfc5483e9e788
Author:     Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Wed May 12 23:31:20 2021 +0200
Commit:     Jérôme Gardou <zefklop(a)users.noreply.github.com>
CommitDate: Wed May 19 22:50:29 2021 +0200
    [NTDLL_APITEST] Add some tests for RtlUnicodeStringToCountedOemString
    CORE-17571
---
 modules/rostests/apitests/ntdll/CMakeLists.txt     |   1 +
 .../ntdll/RtlUnicodeStringToCountedOemString.c     | 136 +++++++++++++++++++++
 modules/rostests/apitests/ntdll/testlist.c         |   2 +
 sdk/include/ndk/rtlfuncs.h                         |   8 ++
 4 files changed, 147 insertions(+)
diff --git a/modules/rostests/apitests/ntdll/CMakeLists.txt
b/modules/rostests/apitests/ntdll/CMakeLists.txt
index d1e4499fb68..684990e2df5 100644
--- a/modules/rostests/apitests/ntdll/CMakeLists.txt
+++ b/modules/rostests/apitests/ntdll/CMakeLists.txt
@@ -80,6 +80,7 @@ list(APPEND SOURCE
     RtlQueryTimeZoneInfo.c
     RtlReAllocateHeap.c
     RtlUnicodeStringToAnsiString.c
+    RtlUnicodeStringToCountedOemString.c
     RtlUpcaseUnicodeStringToCountedOemString.c
     RtlValidateUnicodeString.c
     RtlxUnicodeStringToAnsiSize.c
diff --git a/modules/rostests/apitests/ntdll/RtlUnicodeStringToCountedOemString.c
b/modules/rostests/apitests/ntdll/RtlUnicodeStringToCountedOemString.c
new file mode 100644
index 00000000000..30393fc0ea6
--- /dev/null
+++ b/modules/rostests/apitests/ntdll/RtlUnicodeStringToCountedOemString.c
@@ -0,0 +1,136 @@
+/*
+ * PROJECT:     ReactOS API tests
+ * LICENSE:     LGPL-2.1-or-later (
https://spdx.org/licenses/LGPL-2.1-or-later.html)
+ * PURPOSE:     Test for RtlUnicodeStringToCountedOemString
+ * COPYRIGHT:   Copyright 2021 Jérôme Gardou <jerome.gardou(a)reactos.org>
+ */
+
+#include "precomp.h"
+
+static const struct
+{
+    ULONG AnsiCp;
+    ULONG OemCp;
+    const UNICODE_STRING StrU;
+    NTSTATUS Status;
+    const OEM_STRING StrOem;
+} TestData[] =
+{
+    {
+        1252, 932, /* Western SBCS - Modified SJIS */
+        RTL_CONSTANT_STRING(L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7"),
+        STATUS_BUFFER_OVERFLOW,
+        RTL_CONSTANT_STRING("\x83\x66\x83\x58\x83\x4e")
+    },
+    {
+        932, 1252, /* Modified SJIS - Western SBCS */
+        RTL_CONSTANT_STRING(L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7"),
+        STATUS_UNMAPPABLE_CHARACTER,
+        RTL_CONSTANT_STRING("??????")
+    },
+    {
+        932, 932, /* Modified SJIS - Modified SJIS */
+        RTL_CONSTANT_STRING(L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7"),
+        STATUS_SUCCESS,
+        RTL_CONSTANT_STRING("\x83\x66\x83\x58\x83\x4e\x83\x67\x83\x62\x83\x76")
+    },
+    {
+        1252, 1252, /* Western SBCS */
+        RTL_CONSTANT_STRING(L"\u30c7\u30b9\u30af\u30c8\u30c3\u30d7"), /* Some
japanese characters */
+        STATUS_UNMAPPABLE_CHARACTER,
+        RTL_CONSTANT_STRING("??????")
+    },
+};
+
+START_TEST(RtlUnicodeStringToCountedOemString)
+{
+    WCHAR BufferU[10];
+    CHAR BufferOem[10];
+    UNICODE_STRING StringU;
+    OEM_STRING StringOem;
+    NTSTATUS Status;
+    int i;
+
+    memset(BufferU, 0xAA, sizeof(BufferU));
+    memset(BufferOem, 0xAA, sizeof(BufferOem));
+
+    BufferU[0] = L'A';
+    BufferU[1] = UNICODE_NULL;
+
+    StringU.Buffer = BufferU;
+    StringU.MaximumLength = 10 * sizeof(WCHAR);
+
+    RtlInitUnicodeString(&StringU, BufferU);
+    ok(StringU.Length == 1 * sizeof(WCHAR), "Invalid size: %d\n",
StringU.Length);
+    ok(StringU.MaximumLength == 2 * sizeof(WCHAR), "Invalid size: %d\n",
StringU.MaximumLength);
+    ok(StringU.Buffer == BufferU, "Invalid buffer: %p\n", StringU.Buffer);
+
+    StringOem.Buffer = BufferOem;
+    StringOem.Length = 0;
+    StringOem.MaximumLength = 10 * sizeof(CHAR);
+
+    Status = RtlUnicodeStringToCountedOemString(&StringOem, &StringU, FALSE);
+    ok(NT_SUCCESS(Status), "RtlUnicodeStringToCountedOemString failed: %lx\n",
Status);
+    ok(StringOem.Length == 1 * sizeof(CHAR), "Invalid size: %d\n",
StringOem.Length);
+    ok(StringOem.MaximumLength == 10 * sizeof(CHAR), "Invalid size: %d\n",
StringOem.MaximumLength);
+    ok(StringOem.Buffer == BufferOem, "Invalid buffer: %p\n",
StringOem.Buffer);
+
+    ok(BufferOem[0] == 'A', "Unexpected first char 0x%02x for OEM
string.\n", BufferOem[0]);
+    for (i = 1; i < 10; ++i)
+    {
+        ok(BufferOem[i] == (CHAR)0xAA, "Unexpected char 0x%02x at position
%d.\n", BufferOem[i], i);
+    }
+
+    ok(i == 10, "String was not null terminated!\n");
+
+    /* Test buffer overflow */
+    wcsncpy(BufferU, L"Test", _countof(BufferU));
+    RtlInitUnicodeString(&StringU, BufferU);
+    StringU.MaximumLength = sizeof(BufferU);
+    StringOem.Buffer = BufferOem;
+    StringOem.MaximumLength = 1 * sizeof(CHAR);
+    StringOem.Length = 0;
+    memset(BufferOem, 0xAA, sizeof(BufferOem));
+
+    Status = RtlUnicodeStringToCountedOemString(&StringOem, &StringU, FALSE);
+    ok_ntstatus(Status, STATUS_BUFFER_OVERFLOW);
+    ok(StringOem.Length == 4 * sizeof(CHAR), "Invalid size: %d\n",
StringOem.Length);
+    ok(StringOem.MaximumLength == 1 * sizeof(CHAR), "Invalid size: %d\n",
StringOem.MaximumLength);
+    ok(StringOem.Buffer == BufferOem, "Invalid buffer: %p\n",
StringOem.Buffer);
+
+    for (i = 0; i < 10; ++i)
+    {
+        ok(BufferOem[i] == (CHAR)0xAA, "Unexpected char 0x%02x at position
%d.\n", BufferOem[i], i);
+    }
+
+    for (i = 0; i < _countof(TestData); i++)
+    {
+        SetupLocale(TestData[i].AnsiCp, TestData[i].OemCp, -1);
+
+        trace("Testing locale %u. ANSI: %u, OEM %u\n", i,
(UINT)TestData[i].AnsiCp, (UINT)TestData[i].OemCp);
+
+        /* Get the right length */
+        StringOem.Buffer = NULL;
+        StringOem.Length = 0;
+        StringOem.MaximumLength = 0;
+
+        Status = RtlUnicodeStringToCountedOemString(&StringOem,
&TestData[i].StrU, FALSE);
+        ok_ntstatus(Status, STATUS_BUFFER_OVERFLOW);
+        ok_long(StringOem.Length, TestData[i].StrOem.Length);
+        ok_long(StringOem.MaximumLength, 0);
+
+        StringOem.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
StringOem.Length);
+        StringOem.MaximumLength = StringOem.Length;
+        StringOem.Length = 0;
+
+        Status = RtlUnicodeStringToCountedOemString(&StringOem,
&TestData[i].StrU, FALSE);
+        ok_ntstatus(Status, TestData[i].Status);
+
+        ok_long(StringOem.Length, TestData[i].StrOem.Length);
+        ok_long(StringOem.MaximumLength, TestData[i].StrOem.Length); /* Untouched */
+        ok_long(memcmp(StringOem.Buffer, TestData[i].StrOem.Buffer, min(StringOem.Length,
TestData[i].StrOem.Length)), 0);
+
+        RtlFreeHeap(RtlGetProcessHeap(), 0, StringOem.Buffer);
+    }
+}
+
diff --git a/modules/rostests/apitests/ntdll/testlist.c
b/modules/rostests/apitests/ntdll/testlist.c
index 78a8af20a05..5d4b00b0cce 100644
--- a/modules/rostests/apitests/ntdll/testlist.c
+++ b/modules/rostests/apitests/ntdll/testlist.c
@@ -76,6 +76,7 @@ extern void func_RtlpEnsureBufferSize(void);
 extern void func_RtlQueryTimeZoneInformation(void);
 extern void func_RtlReAllocateHeap(void);
 extern void func_RtlUnicodeStringToAnsiString(void);
+extern void func_RtlUnicodeStringToCountedOemString(void);
 extern void func_RtlUpcaseUnicodeStringToCountedOemString(void);
 extern void func_RtlValidateUnicodeString(void);
 extern void func_RtlxUnicodeStringToAnsiSize(void);
@@ -159,6 +160,7 @@ const struct test winetest_testlist[] =
     { "RtlReAllocateHeap",              func_RtlReAllocateHeap },
     { "RtlUnicodeStringToAnsiSize",     func_RtlxUnicodeStringToAnsiSize }, /*
For some reason, starting test name with Rtlx hides it */
     { "RtlUnicodeStringToAnsiString",   func_RtlUnicodeStringToAnsiString },
+    { "RtlUnicodeStringToCountedOemString",
func_RtlUnicodeStringToCountedOemString },
     { "RtlUnicodeStringToOemSize",      func_RtlxUnicodeStringToOemSize },
     { "RtlUpcaseUnicodeStringToCountedOemString",
func_RtlUpcaseUnicodeStringToCountedOemString },
     { "RtlValidateUnicodeString",       func_RtlValidateUnicodeString },
diff --git a/sdk/include/ndk/rtlfuncs.h b/sdk/include/ndk/rtlfuncs.h
index 513fc195b5f..60e1308b964 100644
--- a/sdk/include/ndk/rtlfuncs.h
+++ b/sdk/include/ndk/rtlfuncs.h
@@ -1879,6 +1879,14 @@ RtlUnicodeStringToOemString(
     BOOLEAN AllocateDestinationString
 );
+NTSYSAPI
+NTSTATUS
+NTAPI
+RtlUnicodeStringToCountedOemString(
+    _Inout_ POEM_STRING OemDest,
+    _In_ PCUNICODE_STRING UniSource,
+    _In_ BOOLEAN AllocateDestinationString);
+
 NTSYSAPI
 NTSTATUS
 NTAPI