https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3e7e4ee360a46cc48c818…
commit 3e7e4ee360a46cc48c818c40f905d1b901e6d3c8
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Mon Feb 15 20:10:59 2021 +0100
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Sat May 8 19:24:23 2021 +0200
[RTL] Implement RtlpApplyLengthFunction
CORE-17248
---
modules/rostests/apitests/ntdll/CMakeLists.txt | 1 +
.../apitests/ntdll/RtlpApplyLengthFunction.c | 143 +++++++++++++++++++++
modules/rostests/apitests/ntdll/testlist.c | 2 +
sdk/lib/rtl/path.c | 45 ++++++-
4 files changed, 188 insertions(+), 3 deletions(-)
diff --git a/modules/rostests/apitests/ntdll/CMakeLists.txt
b/modules/rostests/apitests/ntdll/CMakeLists.txt
index ed0a199a903..545d935e144 100644
--- a/modules/rostests/apitests/ntdll/CMakeLists.txt
+++ b/modules/rostests/apitests/ntdll/CMakeLists.txt
@@ -73,6 +73,7 @@ list(APPEND SOURCE
RtlMemoryStream.c
RtlMultipleAllocateHeap.c
RtlNtPathNameToDosPathName.c
+ RtlpApplyLengthFunction.c
RtlpEnsureBufferSize.c
RtlQueryTimeZoneInfo.c
RtlReAllocateHeap.c
diff --git a/modules/rostests/apitests/ntdll/RtlpApplyLengthFunction.c
b/modules/rostests/apitests/ntdll/RtlpApplyLengthFunction.c
new file mode 100644
index 00000000000..60b9ee6a53e
--- /dev/null
+++ b/modules/rostests/apitests/ntdll/RtlpApplyLengthFunction.c
@@ -0,0 +1,143 @@
+/*
+ * PROJECT: ReactOS API Tests
+ * LICENSE: LGPL-2.1-or-later (
https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE: Test for RtlpApplyLengthFunction
+ * COPYRIGHT: Copyright 2021 Mark Jansen <mark.jansen(a)reactos.org>
+ */
+
+#include "precomp.h"
+#include <ntstrsafe.h>
+
+
+NTSTATUS
+NTAPI
+RtlpApplyLengthFunction(IN ULONG Flags,
+ IN ULONG Type,
+ IN PVOID UnicodeStringOrUnicodeStringBuffer,
+ IN NTSTATUS(NTAPI*LengthFunction)(ULONG, PUNICODE_STRING, PULONG));
+
+
+NTSTATUS NTAPI LengthFunctionFail(ULONG Unknown, PUNICODE_STRING String, PULONG Length)
+{
+ ok_int(*Length, 0);
+ /* Show that this is ignored when an error is returned */
+ *Length = 3;
+ return STATUS_INVALID_ACCOUNT_NAME;
+}
+
+NTSTATUS NTAPI LengthFunctionOk(ULONG Unknown, PUNICODE_STRING String, PULONG Length)
+{
+ ok_int(*Length, 0);
+ *Length = 4;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI LengthFunctionReturn1(ULONG Unknown, PUNICODE_STRING String, PULONG
Length)
+{
+ ok_int(*Length, 0);
+ *Length = 4;
+ return (NTSTATUS)1;
+}
+
+NTSTATUS NTAPI LengthFunctionCopyLen(ULONG Unknown, PUNICODE_STRING String, PULONG
Length)
+{
+ /* Use Buffer as length, to show that the function does not interpret the contents at
all */
+ *Length = (ULONG)(ULONG_PTR)String->Buffer;
+ return STATUS_SUCCESS;
+}
+
+
+START_TEST(RtlpApplyLengthFunction)
+{
+ NTSTATUS Status;
+ /* Show that RtlpApplyLengthFunction does not interpret anything in the
UNICODE_STRING */
+ UNICODE_STRING String = { 1, 2, (PWSTR)3 };
+ RTL_UNICODE_STRING_BUFFER Buffer;
+ WCHAR StaticBuffer[10] = { 0 };
+ ULONG n;
+
+ Status = RtlpApplyLengthFunction(0, 0, NULL, LengthFunctionFail);
+ ok_int(String.Length, 1);
+ ok_hex(Status, STATUS_INVALID_PARAMETER);
+
+ Status = RtlpApplyLengthFunction(0, 0, &String, LengthFunctionFail);
+ ok_int(String.Length, 1);
+ ok_hex(Status, STATUS_INVALID_PARAMETER);
+
+ /* Show that no flag is accepted */
+ for (n = 0; n < 32; ++n)
+ {
+ Status = RtlpApplyLengthFunction((1 << n), sizeof(String), &String,
LengthFunctionFail);
+ ok_int(String.Length, 1);
+ ok_hex(Status, STATUS_INVALID_PARAMETER);
+ }
+
+ Status = RtlpApplyLengthFunction(0, sizeof(String), &String, NULL);
+ ok_int(String.Length, 1);
+ ok_hex(Status, STATUS_INVALID_PARAMETER);
+
+ /* Still Length 1 when the function returns an error */
+ Status = RtlpApplyLengthFunction(0, sizeof(String), &String,
LengthFunctionFail);
+ ok_int(String.Length, 1);
+ ok_hex(Status, STATUS_INVALID_ACCOUNT_NAME);
+
+ Status = RtlpApplyLengthFunction(0, sizeof(String), &String, LengthFunctionOk);
+ ok_int(String.Length, 8); /* Value returned from LengthFunction is multiplied by
sizeof(WCHAR) */
+ ok_hex(Status, STATUS_SUCCESS);
+
+ String.Length = 1;
+ Status = RtlpApplyLengthFunction(0, sizeof(String), &String,
LengthFunctionReturn1);
+ ok_int(String.Length, 8);
+ ok_hex(Status, STATUS_SUCCESS); /* Returns STATUS_SUCCESS regardless of success code
from the function */
+
+ /* Show max length */
+ String.Buffer = (PWCHAR)UNICODE_STRING_MAX_CHARS;
+ String.Length = 2;
+ Status = RtlpApplyLengthFunction(0, sizeof(String), &String,
LengthFunctionCopyLen);
+ ok_int(String.Length, UNICODE_STRING_MAX_CHARS * sizeof(WCHAR));
+ ok_hex(Status, STATUS_SUCCESS);
+
+ String.Buffer = (PWCHAR)(UNICODE_STRING_MAX_CHARS + 1);
+ String.Length = 2;
+ Status = RtlpApplyLengthFunction(0, sizeof(String), &String,
LengthFunctionCopyLen);
+ ok_int(String.Length, 2); /* Unchanged */
+ ok_hex(Status, STATUS_NAME_TOO_LONG);
+
+ /* Now try it with the RTL_UNICODE_STRING_BUFFER, this works fine on 2k3 but not on
Win10!! */
+ RtlInitBuffer(&Buffer.ByteBuffer, (PUCHAR)StaticBuffer, sizeof(StaticBuffer));
+ /* In this case the Buffer is modified, so we should have a valid UNICODE_STRING! */
+ Buffer.String.Length = 5;
+ Buffer.String.MaximumLength = Buffer.ByteBuffer.StaticSize;
+ Buffer.String.Buffer = (PWSTR)Buffer.ByteBuffer.Buffer;
+ wcscpy(StaticBuffer, L"123456789");
+
+ /* Show that no flag is accepted */
+ for (n = 0; n < 32; ++n)
+ {
+ Status = RtlpApplyLengthFunction((1 << n), sizeof(Buffer), &Buffer,
LengthFunctionFail);
+ ok_int(Buffer.String.Length, 5);
+ ok_hex(Status, STATUS_INVALID_PARAMETER);
+ ok_wstr(StaticBuffer, L"123456789");
+ }
+
+ /* Still Length 1 when the function returns an error */
+ Status = RtlpApplyLengthFunction(0, sizeof(Buffer), &Buffer,
LengthFunctionFail);
+ ok_int(Buffer.String.Length, 5);
+ ok_hex(Status, STATUS_INVALID_ACCOUNT_NAME);
+ ok_wstr(StaticBuffer, L"123456789");
+
+ Status = RtlpApplyLengthFunction(0, sizeof(Buffer), &Buffer, LengthFunctionOk);
+ ok_int(Buffer.String.Length, 8); /* Value returned from LengthFunction is
multiplied by sizeof(WCHAR) */
+ ok_hex(Status, STATUS_SUCCESS);
+ ok_wstr(StaticBuffer, L"1234"); /* Buffer is truncated */
+ ok_wstr(StaticBuffer + 5, L"6789"); /* Rest is not overwritten*/
+
+ Buffer.String.Length = 1;
+ wcscpy(StaticBuffer, L"123456789");
+ Status = RtlpApplyLengthFunction(0, sizeof(Buffer), &Buffer,
LengthFunctionReturn1);
+ ok_int(Buffer.String.Length, 8);
+ ok_hex(Status, STATUS_SUCCESS); /* Returns STATUS_SUCCESS regardless of success code
from the function */
+ ok_wstr(StaticBuffer, L"1234"); /* Buffer is truncated */
+ ok_wstr(StaticBuffer + 5, L"6789"); /* Rest is not overwritten*/
+}
+
diff --git a/modules/rostests/apitests/ntdll/testlist.c
b/modules/rostests/apitests/ntdll/testlist.c
index 8b7df571591..7c9cdb2f694 100644
--- a/modules/rostests/apitests/ntdll/testlist.c
+++ b/modules/rostests/apitests/ntdll/testlist.c
@@ -70,6 +70,7 @@ extern void func_RtlIsNameLegalDOS8Dot3(void);
extern void func_RtlMemoryStream(void);
extern void func_RtlMultipleAllocateHeap(void);
extern void func_RtlNtPathNameToDosPathName(void);
+extern void func_RtlpApplyLengthFunction(void);
extern void func_RtlpEnsureBufferSize(void);
extern void func_RtlQueryTimeZoneInformation(void);
extern void func_RtlReAllocateHeap(void);
@@ -148,6 +149,7 @@ const struct test winetest_testlist[] =
{ "RtlMemoryStream", func_RtlMemoryStream },
{ "RtlMultipleAllocateHeap", func_RtlMultipleAllocateHeap },
{ "RtlNtPathNameToDosPathName", func_RtlNtPathNameToDosPathName },
+ { "RtlpApplyLengthFunction", func_RtlpApplyLengthFunction },
{ "RtlpEnsureBufferSize", func_RtlpEnsureBufferSize },
{ "RtlQueryTimeZoneInformation", func_RtlQueryTimeZoneInformation },
{ "RtlReAllocateHeap", func_RtlReAllocateHeap },
diff --git a/sdk/lib/rtl/path.c b/sdk/lib/rtl/path.c
index 6031ae32087..fb28160141b 100644
--- a/sdk/lib/rtl/path.c
+++ b/sdk/lib/rtl/path.c
@@ -446,10 +446,49 @@ NTAPI
RtlpApplyLengthFunction(IN ULONG Flags,
IN ULONG Type,
IN PVOID UnicodeStringOrUnicodeStringBuffer,
- IN PVOID LengthFunction)
+ IN NTSTATUS(NTAPI* LengthFunction)(ULONG, PUNICODE_STRING,
PULONG))
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ NTSTATUS Status;
+ PUNICODE_STRING String;
+ ULONG Length;
+
+ if (Flags || UnicodeStringOrUnicodeStringBuffer == NULL || LengthFunction == NULL)
+ {
+ DPRINT1("ERROR: Flags=0x%x, UnicodeStringOrUnicodeStringBuffer=%p,
LengthFunction=%p\n",
+ Flags, UnicodeStringOrUnicodeStringBuffer, LengthFunction);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (Type == sizeof(UNICODE_STRING))
+ {
+ String = (PUNICODE_STRING)UnicodeStringOrUnicodeStringBuffer;
+ }
+ else if (Type == sizeof(RTL_UNICODE_STRING_BUFFER))
+ {
+ String =
&((PRTL_UNICODE_STRING_BUFFER)UnicodeStringOrUnicodeStringBuffer)->String;
+ }
+ else
+ {
+ DPRINT1("ERROR: Type = %u\n", Type);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Length = 0;
+ Status = LengthFunction(0, String, &Length);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ if (Length > UNICODE_STRING_MAX_CHARS)
+ return STATUS_NAME_TOO_LONG;
+
+ String->Length = (USHORT)(Length * sizeof(WCHAR));
+
+ if (Type == sizeof(RTL_UNICODE_STRING_BUFFER))
+ {
+ String->Buffer[Length] = UNICODE_NULL;
+ }
+
+ return STATUS_SUCCESS;
}
NTSTATUS