1 /* 2 * PROJECT: ReactOS kernel-mode tests 3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) 4 * PURPOSE: Test driver for kernel32 filesystem tests 5 * COPYRIGHT: Copyright 2013-2017 Thomas Faber <thomas.faber@reactos.org> 6 */ 7 8 #include <kmt_test.h> 9 10 #define NDEBUG 11 #include <debug.h> 12 13 #include "kernel32_test.h" 14 15 static KMT_MESSAGE_HANDLER TestMessageHandler; 16 static KMT_IRP_HANDLER TestDirectoryControl; 17 static KMT_IRP_HANDLER TestQueryInformation; 18 static KMT_IRP_HANDLER TestSetInformation; 19 20 static UNICODE_STRING ExpectedExpression = RTL_CONSTANT_STRING(L"<not set>"); 21 static WCHAR ExpressionBuffer[MAX_PATH]; 22 static BOOLEAN ExpectingSetAttributes = FALSE; 23 static ULONG ExpectedSetAttributes = -1; 24 static BOOLEAN ExpectingQueryAttributes = FALSE; 25 static ULONG ReturnQueryAttributes = -1; 26 27 NTSTATUS 28 TestEntry( 29 IN PDRIVER_OBJECT DriverObject, 30 IN PCUNICODE_STRING RegistryPath, 31 OUT PCWSTR *DeviceName, 32 IN OUT INT *Flags) 33 { 34 NTSTATUS Status = STATUS_SUCCESS; 35 36 PAGED_CODE(); 37 38 UNREFERENCED_PARAMETER(RegistryPath); 39 40 *DeviceName = L"kernel32"; 41 *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE; 42 43 KmtRegisterIrpHandler(IRP_MJ_DIRECTORY_CONTROL, NULL, TestDirectoryControl); 44 KmtRegisterIrpHandler(IRP_MJ_QUERY_INFORMATION, NULL, TestQueryInformation); 45 KmtRegisterIrpHandler(IRP_MJ_SET_INFORMATION, NULL, TestSetInformation); 46 KmtRegisterMessageHandler(0, NULL, TestMessageHandler); 47 48 return Status; 49 } 50 51 VOID 52 TestUnload( 53 IN PDRIVER_OBJECT DriverObject) 54 { 55 PAGED_CODE(); 56 } 57 58 static 59 NTSTATUS 60 TestMessageHandler( 61 IN PDEVICE_OBJECT DeviceObject, 62 IN ULONG ControlCode, 63 IN PVOID Buffer OPTIONAL, 64 IN SIZE_T InLength, 65 IN OUT PSIZE_T OutLength) 66 { 67 NTSTATUS Status = STATUS_SUCCESS; 68 69 PAGED_CODE(); 70 71 switch (ControlCode) 72 { 73 case IOCTL_EXPECT_EXPRESSION: 74 { 75 C_ASSERT(sizeof(ExpressionBuffer) <= UNICODE_STRING_MAX_BYTES); 76 DPRINT("IOCTL_EXPECT_EXPRESSION, InLength = %lu\n", InLength); 77 if (InLength > sizeof(ExpressionBuffer)) 78 return STATUS_BUFFER_OVERFLOW; 79 80 if (InLength % sizeof(WCHAR) != 0) 81 return STATUS_INVALID_PARAMETER; 82 83 RtlInitEmptyUnicodeString(&ExpectedExpression, ExpressionBuffer, sizeof(ExpressionBuffer)); 84 RtlCopyMemory(ExpressionBuffer, Buffer, InLength); 85 ExpectedExpression.Length = (USHORT)InLength; 86 DPRINT("IOCTL_EXPECT_EXPRESSION: %wZ\n", &ExpectedExpression); 87 88 break; 89 } 90 case IOCTL_RETURN_QUERY_ATTRIBUTES: 91 { 92 DPRINT("IOCTL_RETURN_QUERY_ATTRIBUTES, InLength = %lu\n", InLength); 93 if (InLength != sizeof(ULONG)) 94 return STATUS_INVALID_PARAMETER; 95 96 ReturnQueryAttributes = *(PULONG)Buffer; 97 ExpectingQueryAttributes = TRUE; 98 DPRINT("IOCTL_RETURN_QUERY_ATTRIBUTES: %lu\n", ReturnQueryAttributes); 99 break; 100 } 101 case IOCTL_EXPECT_SET_ATTRIBUTES: 102 { 103 DPRINT("IOCTL_EXPECT_SET_ATTRIBUTES, InLength = %lu\n", InLength); 104 if (InLength != sizeof(ULONG)) 105 return STATUS_INVALID_PARAMETER; 106 107 ExpectedSetAttributes = *(PULONG)Buffer; 108 ExpectingSetAttributes = TRUE; 109 DPRINT("IOCTL_EXPECT_SET_ATTRIBUTES: %lu\n", ExpectedSetAttributes); 110 break; 111 } 112 default: 113 return STATUS_NOT_SUPPORTED; 114 } 115 116 return Status; 117 } 118 119 static 120 NTSTATUS 121 TestDirectoryControl( 122 IN PDEVICE_OBJECT DeviceObject, 123 IN PIRP Irp, 124 IN PIO_STACK_LOCATION IoStackLocation) 125 { 126 NTSTATUS Status = STATUS_NOT_SUPPORTED; 127 128 PAGED_CODE(); 129 130 DPRINT("IRP %x/%x\n", IoStackLocation->MajorFunction, IoStackLocation->MinorFunction); 131 ASSERT(IoStackLocation->MajorFunction == IRP_MJ_DIRECTORY_CONTROL); 132 133 ok(IoStackLocation->MinorFunction == IRP_MN_QUERY_DIRECTORY, "Minor function: %u\n", IoStackLocation->MinorFunction); 134 if (IoStackLocation->MinorFunction == IRP_MN_QUERY_DIRECTORY) 135 { 136 ok(IoStackLocation->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation, 137 "FileInformationClass: %d\n", IoStackLocation->Parameters.QueryDirectory.FileInformationClass); 138 if (IoStackLocation->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation) 139 { 140 ok(RtlEqualUnicodeString(IoStackLocation->Parameters.QueryDirectory.FileName, &ExpectedExpression, FALSE), 141 "Expression is '%wZ', expected '%wZ'\n", IoStackLocation->Parameters.QueryDirectory.FileName, &ExpectedExpression); 142 RtlZeroMemory(Irp->UserBuffer, IoStackLocation->Parameters.QueryDirectory.Length); 143 Status = STATUS_SUCCESS; 144 } 145 } 146 147 Irp->IoStatus.Status = Status; 148 Irp->IoStatus.Information = 0; 149 150 IoCompleteRequest(Irp, IO_NO_INCREMENT); 151 152 return Status; 153 } 154 155 static 156 NTSTATUS 157 TestQueryInformation( 158 IN PDEVICE_OBJECT DeviceObject, 159 IN PIRP Irp, 160 IN PIO_STACK_LOCATION IoStackLocation) 161 { 162 NTSTATUS Status = STATUS_NOT_SUPPORTED; 163 PFILE_BASIC_INFORMATION BasicInfo; 164 165 PAGED_CODE(); 166 167 DPRINT("IRP %x/%x\n", IoStackLocation->MajorFunction, IoStackLocation->MinorFunction); 168 ASSERT(IoStackLocation->MajorFunction == IRP_MJ_QUERY_INFORMATION); 169 170 Irp->IoStatus.Information = 0; 171 172 ok_eq_ulong(IoStackLocation->Parameters.QueryFile.FileInformationClass, FileBasicInformation); 173 if (IoStackLocation->Parameters.QueryFile.FileInformationClass == FileBasicInformation) 174 { 175 ok(ExpectingQueryAttributes, "Unexpected QUERY_INFORMATION call\n"); 176 BasicInfo = Irp->AssociatedIrp.SystemBuffer; 177 BasicInfo->CreationTime.QuadPart = 126011664000000000; 178 BasicInfo->LastAccessTime.QuadPart = 130899112800000000; 179 BasicInfo->LastWriteTime.QuadPart = 130899112800000000; 180 BasicInfo->ChangeTime.QuadPart = 130899112800000000; 181 BasicInfo->FileAttributes = ReturnQueryAttributes; 182 ReturnQueryAttributes = -1; 183 ExpectingQueryAttributes = FALSE; 184 Status = STATUS_SUCCESS; 185 Irp->IoStatus.Information = sizeof(*BasicInfo); 186 } 187 188 Irp->IoStatus.Status = Status; 189 190 IoCompleteRequest(Irp, IO_NO_INCREMENT); 191 192 return Status; 193 } 194 195 static 196 NTSTATUS 197 TestSetInformation( 198 IN PDEVICE_OBJECT DeviceObject, 199 IN PIRP Irp, 200 IN PIO_STACK_LOCATION IoStackLocation) 201 { 202 NTSTATUS Status = STATUS_NOT_SUPPORTED; 203 PFILE_BASIC_INFORMATION BasicInfo; 204 205 PAGED_CODE(); 206 207 DPRINT("IRP %x/%x\n", IoStackLocation->MajorFunction, IoStackLocation->MinorFunction); 208 ASSERT(IoStackLocation->MajorFunction == IRP_MJ_SET_INFORMATION); 209 210 ok_eq_ulong(IoStackLocation->Parameters.SetFile.FileInformationClass, FileBasicInformation); 211 if (IoStackLocation->Parameters.SetFile.FileInformationClass == FileBasicInformation) 212 { 213 ok(ExpectingSetAttributes, "Unexpected SET_INFORMATION call\n"); 214 BasicInfo = Irp->AssociatedIrp.SystemBuffer; 215 ok_eq_longlong(BasicInfo->CreationTime.QuadPart, 0LL); 216 ok_eq_longlong(BasicInfo->LastAccessTime.QuadPart, 0LL); 217 ok_eq_longlong(BasicInfo->LastWriteTime.QuadPart, 0LL); 218 ok_eq_longlong(BasicInfo->ChangeTime.QuadPart, 0LL); 219 ok_eq_ulong(BasicInfo->FileAttributes, ExpectedSetAttributes); 220 ExpectedSetAttributes = -1; 221 ExpectingSetAttributes = FALSE; 222 Status = STATUS_SUCCESS; 223 } 224 225 Irp->IoStatus.Status = Status; 226 Irp->IoStatus.Information = 0; 227 228 IoCompleteRequest(Irp, IO_NO_INCREMENT); 229 230 return Status; 231 } 232