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 RtlpApplyLengthFunction
5 * COPYRIGHT: Copyright 2021 Mark Jansen <mark.jansen@reactos.org>
6 */
7
8 #include "precomp.h"
9 #include <ntstrsafe.h>
10
11
12 NTSTATUS
13 NTAPI
14 RtlpApplyLengthFunction(IN ULONG Flags,
15 IN ULONG Type,
16 IN PVOID UnicodeStringOrUnicodeStringBuffer,
17 IN NTSTATUS(NTAPI*LengthFunction)(ULONG, PUNICODE_STRING, PULONG));
18
19
LengthFunctionFail(ULONG Unknown,PUNICODE_STRING String,PULONG Length)20 NTSTATUS NTAPI LengthFunctionFail(ULONG Unknown, PUNICODE_STRING String, PULONG Length)
21 {
22 ok_int(*Length, 0);
23 /* Show that this is ignored when an error is returned */
24 *Length = 3;
25 return STATUS_INVALID_ACCOUNT_NAME;
26 }
27
LengthFunctionOk(ULONG Unknown,PUNICODE_STRING String,PULONG Length)28 NTSTATUS NTAPI LengthFunctionOk(ULONG Unknown, PUNICODE_STRING String, PULONG Length)
29 {
30 ok_int(*Length, 0);
31 *Length = 4;
32 return STATUS_SUCCESS;
33 }
34
LengthFunctionReturn1(ULONG Unknown,PUNICODE_STRING String,PULONG Length)35 NTSTATUS NTAPI LengthFunctionReturn1(ULONG Unknown, PUNICODE_STRING String, PULONG Length)
36 {
37 ok_int(*Length, 0);
38 *Length = 4;
39 return (NTSTATUS)1;
40 }
41
LengthFunctionCopyLen(ULONG Unknown,PUNICODE_STRING String,PULONG Length)42 NTSTATUS NTAPI LengthFunctionCopyLen(ULONG Unknown, PUNICODE_STRING String, PULONG Length)
43 {
44 /* Use Buffer as length, to show that the function does not interpret the contents at all */
45 *Length = (ULONG)(ULONG_PTR)String->Buffer;
46 return STATUS_SUCCESS;
47 }
48
49
START_TEST(RtlpApplyLengthFunction)50 START_TEST(RtlpApplyLengthFunction)
51 {
52 NTSTATUS Status;
53 /* Show that RtlpApplyLengthFunction does not interpret anything in the UNICODE_STRING */
54 UNICODE_STRING String = { 1, 2, (PWSTR)3 };
55 RTL_UNICODE_STRING_BUFFER Buffer;
56 WCHAR StaticBuffer[10] = { 0 };
57 ULONG n;
58
59 Status = RtlpApplyLengthFunction(0, 0, NULL, LengthFunctionFail);
60 ok_int(String.Length, 1);
61 ok_hex(Status, STATUS_INVALID_PARAMETER);
62
63 Status = RtlpApplyLengthFunction(0, 0, &String, LengthFunctionFail);
64 ok_int(String.Length, 1);
65 ok_hex(Status, STATUS_INVALID_PARAMETER);
66
67 /* Show that no flag is accepted */
68 for (n = 0; n < 32; ++n)
69 {
70 Status = RtlpApplyLengthFunction((1 << n), sizeof(String), &String, LengthFunctionFail);
71 ok_int(String.Length, 1);
72 ok_hex(Status, STATUS_INVALID_PARAMETER);
73 }
74
75 Status = RtlpApplyLengthFunction(0, sizeof(String), &String, NULL);
76 ok_int(String.Length, 1);
77 ok_hex(Status, STATUS_INVALID_PARAMETER);
78
79 /* Still Length 1 when the function returns an error */
80 Status = RtlpApplyLengthFunction(0, sizeof(String), &String, LengthFunctionFail);
81 ok_int(String.Length, 1);
82 ok_hex(Status, STATUS_INVALID_ACCOUNT_NAME);
83
84 Status = RtlpApplyLengthFunction(0, sizeof(String), &String, LengthFunctionOk);
85 ok_int(String.Length, 8); /* Value returned from LengthFunction is multiplied by sizeof(WCHAR) */
86 ok_hex(Status, STATUS_SUCCESS);
87
88 String.Length = 1;
89 Status = RtlpApplyLengthFunction(0, sizeof(String), &String, LengthFunctionReturn1);
90 ok_int(String.Length, 8);
91 ok_hex(Status, STATUS_SUCCESS); /* Returns STATUS_SUCCESS regardless of success code from the function */
92
93 /* Show max length */
94 String.Buffer = (PWCHAR)UNICODE_STRING_MAX_CHARS;
95 String.Length = 2;
96 Status = RtlpApplyLengthFunction(0, sizeof(String), &String, LengthFunctionCopyLen);
97 ok_int(String.Length, UNICODE_STRING_MAX_CHARS * sizeof(WCHAR));
98 ok_hex(Status, STATUS_SUCCESS);
99
100 String.Buffer = (PWCHAR)(UNICODE_STRING_MAX_CHARS + 1);
101 String.Length = 2;
102 Status = RtlpApplyLengthFunction(0, sizeof(String), &String, LengthFunctionCopyLen);
103 ok_int(String.Length, 2); /* Unchanged */
104 ok_hex(Status, STATUS_NAME_TOO_LONG);
105
106 /* Now try it with the RTL_UNICODE_STRING_BUFFER, this works fine on 2k3 but not on Win10!! */
107 RtlInitBuffer(&Buffer.ByteBuffer, (PUCHAR)StaticBuffer, sizeof(StaticBuffer));
108 /* In this case the Buffer is modified, so we should have a valid UNICODE_STRING! */
109 Buffer.String.Length = 5;
110 Buffer.String.MaximumLength = Buffer.ByteBuffer.StaticSize;
111 Buffer.String.Buffer = (PWSTR)Buffer.ByteBuffer.Buffer;
112 wcscpy(StaticBuffer, L"123456789");
113
114 /* Show that no flag is accepted */
115 for (n = 0; n < 32; ++n)
116 {
117 Status = RtlpApplyLengthFunction((1 << n), sizeof(Buffer), &Buffer, LengthFunctionFail);
118 ok_int(Buffer.String.Length, 5);
119 ok_hex(Status, STATUS_INVALID_PARAMETER);
120 ok_wstr(StaticBuffer, L"123456789");
121 }
122
123 /* Still Length 1 when the function returns an error */
124 Status = RtlpApplyLengthFunction(0, sizeof(Buffer), &Buffer, LengthFunctionFail);
125 ok_int(Buffer.String.Length, 5);
126 ok_hex(Status, STATUS_INVALID_ACCOUNT_NAME);
127 ok_wstr(StaticBuffer, L"123456789");
128
129 Status = RtlpApplyLengthFunction(0, sizeof(Buffer), &Buffer, LengthFunctionOk);
130 ok_int(Buffer.String.Length, 8); /* Value returned from LengthFunction is multiplied by sizeof(WCHAR) */
131 ok_hex(Status, STATUS_SUCCESS);
132 ok_wstr(StaticBuffer, L"1234"); /* Buffer is truncated */
133 ok_wstr(StaticBuffer + 5, L"6789"); /* Rest is not overwritten*/
134
135 Buffer.String.Length = 1;
136 wcscpy(StaticBuffer, L"123456789");
137 Status = RtlpApplyLengthFunction(0, sizeof(Buffer), &Buffer, LengthFunctionReturn1);
138 ok_int(Buffer.String.Length, 8);
139 ok_hex(Status, STATUS_SUCCESS); /* Returns STATUS_SUCCESS regardless of success code from the function */
140 ok_wstr(StaticBuffer, L"1234"); /* Buffer is truncated */
141 ok_wstr(StaticBuffer + 5, L"6789"); /* Rest is not overwritten*/
142 }
143
144