X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=rostests%2Fkmtests%2Fntos_io%2FIoFilesystem.c;h=c8edfe50fe3b1b881d68f4c45b7a69c15df573aa;hp=bcfc5219f90e1003b3d45bc6bdcd1c2990286002;hb=187db82af702fbf1b9cda19723f6129f48e1349d;hpb=5a28e79cccabfe38a24c26ec0ba2b5fb0a17bc18 diff --git a/rostests/kmtests/ntos_io/IoFilesystem.c b/rostests/kmtests/ntos_io/IoFilesystem.c index bcfc5219f90..c8edfe50fe3 100644 --- a/rostests/kmtests/ntos_io/IoFilesystem.c +++ b/rostests/kmtests/ntos_io/IoFilesystem.c @@ -9,6 +9,201 @@ /* FIXME: Test this stuff on non-FAT volumes */ +static +NTSTATUS +QueryFileInfo( + _In_ HANDLE FileHandle, + _Out_ PVOID *Info, + _Inout_ PSIZE_T Length, + _In_ FILE_INFORMATION_CLASS FileInformationClass) +{ + NTSTATUS Status; + IO_STATUS_BLOCK IoStatus; + PVOID Buffer; + + *Info = NULL; + if (*Length) + { + Buffer = KmtAllocateGuarded(*Length); + if (skip(Buffer != NULL, "Failed to allocate %Iu bytes\n", *Length)) + return STATUS_INSUFFICIENT_RESOURCES; + } + else + { + Buffer = NULL; + } + RtlFillMemory(Buffer, *Length, 0xDD); + RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55); + _SEH2_TRY + { + Status = ZwQueryInformationFile(FileHandle, + &IoStatus, + Buffer, + *Length, + FileInformationClass); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + ok(0, "Exception %lx querying class %d with length %Iu\n", + Status, FileInformationClass, *Length); + } + _SEH2_END; + if (Status == STATUS_PENDING) + { + Status = ZwWaitForSingleObject(FileHandle, FALSE, NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = IoStatus.Status; + } + *Length = IoStatus.Information; + *Info = Buffer; + return Status; +} + +static +VOID +TestAllInformation(VOID) +{ + NTSTATUS Status; + UNICODE_STRING FileName = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\ntoskrnl.exe"); + UNICODE_STRING Ntoskrnl = RTL_CONSTANT_STRING(L"ntoskrnl.exe"); + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE FileHandle; + IO_STATUS_BLOCK IoStatus; + PFILE_ALL_INFORMATION FileAllInfo; + SIZE_T Length; + ULONG NameLength; + PWCHAR Name = NULL; + UNICODE_STRING NamePart; + + InitializeObjectAttributes(&ObjectAttributes, + &FileName, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenFile(&FileHandle, + SYNCHRONIZE | FILE_READ_ATTRIBUTES, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_NON_DIRECTORY_FILE); + if (Status == STATUS_PENDING) + { + Status = ZwWaitForSingleObject(FileHandle, FALSE, NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + Status = IoStatus.Status; + } + ok_eq_hex(Status, STATUS_SUCCESS); + if (skip(NT_SUCCESS(Status), "No file handle, %lx\n", Status)) + return; + + /* NtQueryInformationFile doesn't do length checks for kernel callers in a free build */ + if (KmtIsCheckedBuild) + { + /* Zero length */ + Length = 0; + Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); + ok_eq_hex(Status, STATUS_INFO_LENGTH_MISMATCH); + ok_eq_size(Length, (ULONG_PTR)0x5555555555555555); + if (FileAllInfo) + KmtFreeGuarded(FileAllInfo); + + /* One less than the minimum */ + Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) - 1; + Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); + ok_eq_hex(Status, STATUS_INFO_LENGTH_MISMATCH); + ok_eq_size(Length, (ULONG_PTR)0x5555555555555555); + if (FileAllInfo) + KmtFreeGuarded(FileAllInfo); + } + + /* The minimum allowed */ + Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName); + Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); + ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW); + ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName)); + if (FileAllInfo) + KmtFreeGuarded(FileAllInfo); + + /* Plenty of space -- determine NameLength and copy the name */ + Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + MAX_PATH * sizeof(WCHAR); + Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); + ok_eq_hex(Status, STATUS_SUCCESS); + if (!skip(NT_SUCCESS(Status) && FileAllInfo != NULL, "No info\n")) + { + NameLength = FileAllInfo->NameInformation.FileNameLength; + ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength); + Name = ExAllocatePoolWithTag(PagedPool, NameLength + sizeof(UNICODE_NULL), 'sFmK'); + if (!skip(Name != NULL, "Could not allocate %lu bytes\n", NameLength + (ULONG)sizeof(UNICODE_NULL))) + { + RtlCopyMemory(Name, + FileAllInfo->NameInformation.FileName, + NameLength); + Name[NameLength / sizeof(WCHAR)] = UNICODE_NULL; + ok(Name[0] == L'\\', "Name is %ls, expected first char to be \\\n", Name); + ok(NameLength >= Ntoskrnl.Length + sizeof(WCHAR), "NameLength %lu too short\n", NameLength); + if (NameLength >= Ntoskrnl.Length) + { + NamePart.Buffer = Name + (NameLength - Ntoskrnl.Length) / sizeof(WCHAR); + NamePart.Length = Ntoskrnl.Length; + NamePart.MaximumLength = NamePart.Length; + ok(RtlEqualUnicodeString(&NamePart, &Ntoskrnl, TRUE), + "Name ends in '%wZ', expected %wZ\n", &NamePart, &Ntoskrnl); + } + } + ok(FileAllInfo->NameInformation.FileName[NameLength / sizeof(WCHAR)] == 0xdddd, + "Char past FileName is %x\n", + FileAllInfo->NameInformation.FileName[NameLength / sizeof(WCHAR)]); + } + if (FileAllInfo) + KmtFreeGuarded(FileAllInfo); + + /* One char less than needed */ + Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - sizeof(WCHAR); + Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); + ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW); + ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - sizeof(WCHAR)); + if (FileAllInfo) + KmtFreeGuarded(FileAllInfo); + + /* One byte less than needed */ + Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - 1; + Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); + ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW); + ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - 1); + if (FileAllInfo) + KmtFreeGuarded(FileAllInfo); + + /* Exactly the required size */ + Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength; + Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); + ok_eq_hex(Status, STATUS_SUCCESS); + ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength); + if (FileAllInfo) + KmtFreeGuarded(FileAllInfo); + + /* One byte more than needed */ + Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength + 1; + Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); + ok_eq_hex(Status, STATUS_SUCCESS); + ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength); + if (FileAllInfo) + KmtFreeGuarded(FileAllInfo); + + /* One char more than needed */ + Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength + sizeof(WCHAR); + Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); + ok_eq_hex(Status, STATUS_SUCCESS); + ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength); + if (FileAllInfo) + KmtFreeGuarded(FileAllInfo); + + ExFreePoolWithTag(Name, 'sFmK'); + + Status = ObCloseHandle(FileHandle, KernelMode); + ok_eq_hex(Status, STATUS_SUCCESS); +} + static VOID Substitute( @@ -443,6 +638,7 @@ Cleanup: START_TEST(IoFilesystem) { + TestAllInformation(); TestRelativeNames(); TestSharedCacheMap(); }