Author: tfaber
Date: Mon Nov 16 13:53:03 2015
New Revision: 69897
URL:
http://svn.reactos.org/svn/reactos?rev=69897&view=rev
Log:
[KMTESTS:IO]
- Add a test for FileAllInformation
Modified:
trunk/rostests/kmtests/ntos_io/IoFilesystem.c
Modified: trunk/rostests/kmtests/ntos_io/IoFilesystem.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/kmtests/ntos_io/IoFilesys…
==============================================================================
--- trunk/rostests/kmtests/ntos_io/IoFilesystem.c [iso-8859-1] (original)
+++ trunk/rostests/kmtests/ntos_io/IoFilesystem.c [iso-8859-1] Mon Nov 16 13:53:03 2015
@@ -8,6 +8,201 @@
#include <kmt_test.h>
/* 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
@@ -443,6 +638,7 @@
START_TEST(IoFilesystem)
{
+ TestAllInformation();
TestRelativeNames();
TestSharedCacheMap();
}