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 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 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 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 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 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