static VOID NTAPI KernelModeTest(IN PVOID Context) { NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE ParentHandle, SystemRootHandle, TargetHandle; PFILE_OBJECT ParentFileObject, TargetFileObject, SystemRootFileObject; UNREFERENCED_PARAMETER(Context); /* Kernelmode mandatory for IoCreateFile */ ok(ExGetPreviousMode() == KernelMode, "UserMode returned!\n"); /* First of all, open \\SystemRoot * We're interested in 3 pieces of information about it: * -> Its target (it's a symlink): \Windows or \ReactOS * -> Its associated File Object * -> Its associated FCB */ TargetFileObject = NULL; IoStatusBlock.Status = 0xFFFFFFFF; TargetHandle = INVALID_HANDLE_VALUE; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRoot, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenFile(&TargetHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { Status = ObReferenceObjectByHandle(TargetHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, (PVOID *)&TargetFileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); } ok(TargetFileObject != NULL, "Not target to continue!\n"); if (TargetFileObject == NULL) { if (TargetHandle != INVALID_HANDLE_VALUE) { ObCloseHandle(TargetHandle, KernelMode); } return; } /* Open target directory of \SystemRoot\Regedit.exe * This must lead to \SystemRoot opening */ IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRootRegedit, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = IoCreateFile(&ParentHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_OPEN_TARGET_DIRECTORY); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { Status = ObReferenceObjectByHandle(ParentHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, (PVOID *)&ParentFileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { /* At that point, file object must point to \SystemRoot * But must not be the same FO than target (diverted file object) * This means FCB & FileName are equal * But CCB & FO are different * CCB must be != NULL, otherwise it means open failed */ ok(ParentFileObject != TargetFileObject, "Diverted file object must be different\n"); ok_eq_pointer(ParentFileObject->RelatedFileObject, NULL); ok_eq_pointer(ParentFileObject->FsContext, TargetFileObject->FsContext); ok(ParentFileObject->FsContext2 != 0x0, "Parent must be open!\n"); ok(ParentFileObject->FsContext2 != TargetFileObject->FsContext2, "Parent open must have its own context!\n"); ok_eq_long(RtlCompareUnicodeString(&ParentFileObject->FileName, &TargetFileObject->FileName, FALSE), 0); ObDereferenceObject(ParentFileObject); } /* Because target exists FSD must signal it */ ok_eq_long(IoStatusBlock.Information, FILE_EXISTS); ObCloseHandle(ParentHandle, KernelMode); } /* Do the same with relative open */ IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRoot, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenFile(&SystemRootHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &Regedit, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, SystemRootHandle, NULL); Status = IoCreateFile(&ParentHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_OPEN_TARGET_DIRECTORY); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { Status = ObReferenceObjectByHandle(ParentHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, (PVOID *)&ParentFileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { ok(ParentFileObject != TargetFileObject, "Diverted file object must be different\n"); ok_eq_pointer(ParentFileObject->FsContext, TargetFileObject->FsContext); ok(ParentFileObject->FsContext2 != 0x0, "Parent must be open!\n"); ok(ParentFileObject->FsContext2 != TargetFileObject->FsContext2, "Parent open must have its own context!\n"); ok_eq_long(RtlCompareUnicodeString(&ParentFileObject->FileName, &TargetFileObject->FileName, FALSE), 0); Status = ObReferenceObjectByHandle(SystemRootHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, (PVOID *)&SystemRootFileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { ok_eq_pointer(ParentFileObject->RelatedFileObject, SystemRootFileObject); ok(ParentFileObject->RelatedFileObject != TargetFileObject, "File objects must be different\n"); ok(SystemRootFileObject != TargetFileObject, "File objects must be different\n"); ObDereferenceObject(SystemRootFileObject); } ObDereferenceObject(ParentFileObject); } ok_eq_long(IoStatusBlock.Information, FILE_EXISTS); ObCloseHandle(ParentHandle, KernelMode); } ObCloseHandle(SystemRootHandle, KernelMode); } /* *** */ /* Now redo the same scheme, but using a target that doesn't exist * The difference will be in IoStatusBlock.Information, the FSD will * inform that the target doesn't exist. * Clear for rename :-) */ IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRootFoobar, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = IoCreateFile(&ParentHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_OPEN_TARGET_DIRECTORY); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { Status = ObReferenceObjectByHandle(ParentHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, (PVOID *)&ParentFileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { ok(ParentFileObject != TargetFileObject, "Diverted file object must be different\n"); ok_eq_pointer(ParentFileObject->RelatedFileObject, NULL); ok_eq_pointer(ParentFileObject->FsContext, TargetFileObject->FsContext); ok(ParentFileObject->FsContext2 != 0x0, "Parent must be open!\n"); ok(ParentFileObject->FsContext2 != TargetFileObject->FsContext2, "Parent open must have its own context!\n"); ok_eq_long(RtlCompareUnicodeString(&ParentFileObject->FileName, &TargetFileObject->FileName, FALSE), 0); ObDereferenceObject(ParentFileObject); } ok_eq_long(IoStatusBlock.Information, FILE_DOES_NOT_EXIST); ObCloseHandle(ParentHandle, KernelMode); } IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRoot, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenFile(&SystemRootHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &Foobar, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, SystemRootHandle, NULL); Status = IoCreateFile(&ParentHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_OPEN_TARGET_DIRECTORY); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { Status = ObReferenceObjectByHandle(ParentHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, (PVOID *)&ParentFileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { ok(ParentFileObject != TargetFileObject, "Diverted file object must be different\n"); ok_eq_pointer(ParentFileObject->FsContext, TargetFileObject->FsContext); ok(ParentFileObject->FsContext2 != 0x0, "Parent must be open!\n"); ok(ParentFileObject->FsContext2 != TargetFileObject->FsContext2, "Parent open must have its own context!\n"); ok_eq_long(RtlCompareUnicodeString(&ParentFileObject->FileName, &TargetFileObject->FileName, FALSE), 0); Status = ObReferenceObjectByHandle(SystemRootHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, (PVOID *)&SystemRootFileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { ok_eq_pointer(ParentFileObject->RelatedFileObject, SystemRootFileObject); ok(ParentFileObject->RelatedFileObject != TargetFileObject, "File objects must be different\n"); ok(SystemRootFileObject != TargetFileObject, "File objects must be different\n"); ObDereferenceObject(SystemRootFileObject); } ObDereferenceObject(ParentFileObject); } ok_eq_long(IoStatusBlock.Information, FILE_DOES_NOT_EXIST); ObCloseHandle(ParentHandle, KernelMode); } ObCloseHandle(SystemRootHandle, KernelMode); } ObDereferenceObject(TargetFileObject); ObCloseHandle(TargetHandle, KernelMode); /* *** */ /* Direct target open of something that doesn't exist */ IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRootFoobarFoobar, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = IoCreateFile(&ParentHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_OPEN_TARGET_DIRECTORY); ok_eq_hex(Status, STATUS_OBJECT_PATH_NOT_FOUND); ok_eq_hex(IoStatusBlock.Status, 0xFFFFFFFF); if (Status == STATUS_SUCCESS) { ObCloseHandle(ParentHandle, KernelMode); } /* Relative target open of something that doesn't exist */ IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRoot, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenFile(&SystemRootHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &FoobarFoobar, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, SystemRootHandle, NULL); Status = IoCreateFile(&ParentHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_OPEN_TARGET_DIRECTORY); ok_eq_hex(Status, STATUS_OBJECT_PATH_NOT_FOUND); ok_eq_hex(IoStatusBlock.Status, 0xFFFFFFFF); if (Status == STATUS_SUCCESS) { ObCloseHandle(ParentHandle, KernelMode); } ObCloseHandle(SystemRootHandle, KernelMode); } }
static VOID TestVolumeInfo( IN HANDLE ServerHandle) { NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; FILE_FS_SIZE_INFORMATION FileFsSizeInfo; FILE_FS_DEVICE_INFORMATION FileFsDeviceInfo; FILE_FS_FULL_SIZE_INFORMATION FileFsFullSizeInfo; struct { FILE_FS_VOLUME_INFORMATION; WCHAR PartialName[10]; } VolumeInfo; struct { FILE_FS_ATTRIBUTE_INFORMATION; WCHAR PartialName[6]; } AttributeInfo; RtlFillMemory(&VolumeInfo, sizeof(VolumeInfo), 0xFF); Status = ZwQueryVolumeInformationFile(ServerHandle, &IoStatusBlock, &VolumeInfo, sizeof(VolumeInfo), FileFsVolumeInformation); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); ok_eq_long(VolumeInfo.VolumeCreationTime.LowPart, 0); ok_eq_long(VolumeInfo.VolumeCreationTime.HighPart, 0); ok_eq_ulong(VolumeInfo.VolumeSerialNumber, 0); ok_bool_false(VolumeInfo.SupportsObjects, "VolumeInfo.SupportsObjects"); ok_eq_ulong(VolumeInfo.VolumeLabelLength, 18); ok_eq_size(RtlCompareMemory(VolumeInfo.VolumeLabel, L"NamedPipe", 18), 18); ok_eq_wchar(VolumeInfo.VolumeLabel[9], 0xFFFF); ok_eq_ulong(IoStatusBlock.Information, (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + 9 * sizeof(WCHAR))); RtlFillMemory(&VolumeInfo, sizeof(VolumeInfo), 0xFF); Status = ZwQueryVolumeInformationFile(ServerHandle, &IoStatusBlock, &VolumeInfo, sizeof(FILE_FS_VOLUME_INFORMATION) + 2 * sizeof(WCHAR), FileFsVolumeInformation); ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW); ok_eq_hex(IoStatusBlock.Status, STATUS_BUFFER_OVERFLOW); ok_eq_long(VolumeInfo.VolumeCreationTime.LowPart, 0); ok_eq_long(VolumeInfo.VolumeCreationTime.HighPart, 0); ok_eq_ulong(VolumeInfo.VolumeSerialNumber, 0); ok_bool_false(VolumeInfo.SupportsObjects, "VolumeInfo.SupportsObjects"); ok_eq_ulong(VolumeInfo.VolumeLabelLength, 18); ok_eq_size(RtlCompareMemory(VolumeInfo.VolumeLabel, L"NamedP", 10), 10); ok_eq_wchar(VolumeInfo.VolumeLabel[5], 0xFFFF); ok_eq_ulong(IoStatusBlock.Information, (FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel) + 5 * sizeof(WCHAR))); RtlFillMemory(&FileFsSizeInfo, sizeof(FileFsSizeInfo), 0xFF); Status = ZwQueryVolumeInformationFile(ServerHandle, &IoStatusBlock, &FileFsSizeInfo, sizeof(FileFsSizeInfo), FileFsSizeInformation); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); ok_eq_longlong(FileFsSizeInfo.TotalAllocationUnits.QuadPart, 0); ok_eq_longlong(FileFsSizeInfo.AvailableAllocationUnits.QuadPart, 0); ok_eq_ulong(FileFsSizeInfo.SectorsPerAllocationUnit, 1); ok_eq_ulong(FileFsSizeInfo.BytesPerSector, 1); ok_eq_ulong(IoStatusBlock.Information, sizeof(FileFsSizeInfo)); RtlFillMemory(&FileFsSizeInfo, sizeof(FileFsSizeInfo), 0xFF); Status = ZwQueryVolumeInformationFile(ServerHandle, &IoStatusBlock, &FileFsSizeInfo, sizeof(FileFsSizeInfo) - 4, FileFsSizeInformation); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); ok_eq_longlong(FileFsSizeInfo.TotalAllocationUnits.QuadPart, 0); ok_eq_longlong(FileFsSizeInfo.AvailableAllocationUnits.QuadPart, 0); ok_eq_ulong(FileFsSizeInfo.SectorsPerAllocationUnit, 1); ok_eq_ulong(FileFsSizeInfo.BytesPerSector, 1); ok_eq_ulong(IoStatusBlock.Information, sizeof(FileFsSizeInfo)); RtlFillMemory(&FileFsDeviceInfo, sizeof(FileFsDeviceInfo), 0xFF); Status = ZwQueryVolumeInformationFile(ServerHandle, &IoStatusBlock, &FileFsDeviceInfo, sizeof(FileFsDeviceInfo), FileFsDeviceInformation); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); ok_eq_ulong(FileFsDeviceInfo.Characteristics, 0); ok_eq_ulong(FileFsDeviceInfo.DeviceType, FILE_DEVICE_NAMED_PIPE); ok_eq_ulong(IoStatusBlock.Information, sizeof(FileFsDeviceInfo)); RtlFillMemory(&FileFsDeviceInfo, sizeof(FileFsDeviceInfo), 0xFF); Status = ZwQueryVolumeInformationFile(ServerHandle, &IoStatusBlock, &FileFsDeviceInfo, sizeof(FileFsDeviceInfo) - 4, FileFsDeviceInformation); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); ok_eq_ulong(FileFsDeviceInfo.Characteristics, 0); ok_eq_ulong(FileFsDeviceInfo.DeviceType, FILE_DEVICE_NAMED_PIPE); ok_eq_ulong(IoStatusBlock.Information, sizeof(FileFsDeviceInfo)); RtlFillMemory(&AttributeInfo, sizeof(AttributeInfo), 0xFF); Status = ZwQueryVolumeInformationFile(ServerHandle, &IoStatusBlock, &AttributeInfo, sizeof(AttributeInfo), FileFsAttributeInformation); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); ok_eq_ulong(AttributeInfo.FileSystemAttributes, FILE_CASE_PRESERVED_NAMES); ok_eq_long(AttributeInfo.MaximumComponentNameLength, 0xFFFFFFFF); ok_eq_ulong(AttributeInfo.FileSystemNameLength, 8); ok_eq_size(RtlCompareMemory(AttributeInfo.FileSystemName, L"NPFS", 8), 8); ok_eq_wchar(AttributeInfo.FileSystemName[4], 0xFFFF); ok_eq_ulong(IoStatusBlock.Information, 20); RtlFillMemory(&AttributeInfo, sizeof(AttributeInfo), 0xFF); Status = ZwQueryVolumeInformationFile(ServerHandle, &IoStatusBlock, &AttributeInfo, sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 2 * sizeof(WCHAR), FileFsAttributeInformation); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); ok_eq_ulong(AttributeInfo.FileSystemAttributes, FILE_CASE_PRESERVED_NAMES); ok_eq_long(AttributeInfo.MaximumComponentNameLength, 0xFFFFFFFF); ok_eq_ulong(AttributeInfo.FileSystemNameLength, 8); ok_eq_size(RtlCompareMemory(AttributeInfo.FileSystemName, L"NPFS", 8), 8); ok_eq_wchar(AttributeInfo.FileSystemName[4], 0xFFFF); ok_eq_ulong(IoStatusBlock.Information, 20); RtlFillMemory(&FileFsFullSizeInfo, sizeof(FileFsFullSizeInfo), 0xFF); Status = ZwQueryVolumeInformationFile(ServerHandle, &IoStatusBlock, &FileFsFullSizeInfo, sizeof(FileFsFullSizeInfo), FileFsFullSizeInformation); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); ok_eq_longlong(FileFsFullSizeInfo.TotalAllocationUnits.QuadPart, 0); ok_eq_longlong(FileFsFullSizeInfo.CallerAvailableAllocationUnits.QuadPart, 0); ok_eq_longlong(FileFsFullSizeInfo.ActualAvailableAllocationUnits.QuadPart, 0); ok_eq_ulong(FileFsFullSizeInfo.SectorsPerAllocationUnit, 0); ok_eq_ulong(FileFsFullSizeInfo.BytesPerSector, 0); ok_eq_ulong(IoStatusBlock.Information, sizeof(FileFsFullSizeInfo)); RtlFillMemory(&FileFsFullSizeInfo, sizeof(FileFsFullSizeInfo), 0xFF); Status = ZwQueryVolumeInformationFile(ServerHandle, &IoStatusBlock, &FileFsFullSizeInfo, sizeof(FileFsFullSizeInfo) - 4, FileFsFullSizeInformation); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); ok_eq_longlong(FileFsFullSizeInfo.TotalAllocationUnits.QuadPart, 0); ok_eq_longlong(FileFsFullSizeInfo.CallerAvailableAllocationUnits.QuadPart, 0); ok_eq_longlong(FileFsFullSizeInfo.ActualAvailableAllocationUnits.QuadPart, 0); ok_eq_ulong(FileFsFullSizeInfo.SectorsPerAllocationUnit, 0); ok_eq_ulong(FileFsFullSizeInfo.BytesPerSector, 0); ok_eq_ulong(IoStatusBlock.Information, sizeof(FileFsFullSizeInfo)); }
static VOID TestEventConcurrent( IN PKEVENT Event, IN EVENT_TYPE Type, IN KIRQL OriginalIrql, PSET_EVENT_FUNCTION SetEvent, KPRIORITY PriorityIncrement, LONG ExpectedState, BOOLEAN SatisfiesAll) { NTSTATUS Status; THREAD_DATA Threads[5]; const INT ThreadCount = sizeof Threads / sizeof Threads[0]; KPRIORITY Priority; LARGE_INTEGER LongTimeout, ShortTimeout; INT i; KWAIT_BLOCK WaitBlock[MAXIMUM_WAIT_OBJECTS]; PVOID ThreadObjects[MAXIMUM_WAIT_OBJECTS]; LONG State; PKTHREAD Thread = KeGetCurrentThread(); LongTimeout.QuadPart = -100 * MILLISECOND; ShortTimeout.QuadPart = -1 * MILLISECOND; KeInitializeEvent(Event, Type, FALSE); for (i = 0; i < ThreadCount; ++i) { Threads[i].Event = Event; Threads[i].Signal = FALSE; Status = PsCreateSystemThread(&Threads[i].Handle, GENERIC_ALL, NULL, NULL, NULL, WaitForEventThread, &Threads[i]); ok_eq_hex(Status, STATUS_SUCCESS); Status = ObReferenceObjectByHandle(Threads[i].Handle, SYNCHRONIZE, PsThreadType, KernelMode, (PVOID *)&Threads[i].Thread, NULL); ok_eq_hex(Status, STATUS_SUCCESS); ThreadObjects[i] = Threads[i].Thread; Priority = KeQueryPriorityThread(Threads[i].Thread); ok_eq_long(Priority, 8L); while (!Threads[i].Signal) { Status = KeDelayExecutionThread(KernelMode, FALSE, &ShortTimeout); ok_eq_hex(Status, STATUS_SUCCESS); } CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, ThreadObjects, i + 1); } /* the threads shouldn't wake up on their own */ Status = KeDelayExecutionThread(KernelMode, FALSE, &ShortTimeout); ok_eq_hex(Status, STATUS_SUCCESS); for (i = 0; i < ThreadCount; ++i) { CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, ThreadObjects + i, ThreadCount - i); State = SetEvent(Event, PriorityIncrement + i, FALSE); ok_eq_long(State, 0L); CheckEvent(Event, Type, ExpectedState, FALSE, OriginalIrql, ThreadObjects + i + 1, SatisfiesAll ? 0 : ThreadCount - i - 1); Status = KeWaitForMultipleObjects(ThreadCount, ThreadObjects, SatisfiesAll ? WaitAll : WaitAny, Executive, KernelMode, FALSE, &LongTimeout, WaitBlock); ok_eq_hex(Status, STATUS_WAIT_0 + i); if (SatisfiesAll) { for (; i < ThreadCount; ++i) { Priority = KeQueryPriorityThread(Threads[i].Thread); ok_eq_long(Priority, max(min(8L + PriorityIncrement, 15L), 8L)); } break; } Priority = KeQueryPriorityThread(Threads[i].Thread); ok_eq_long(Priority, max(min(8L + PriorityIncrement + i, 15L), 8L)); /* replace the thread with the current thread - which will never signal */ if (!skip((Status & 0x3F) < ThreadCount, "Index out of bounds")) ThreadObjects[Status & 0x3F] = Thread; Status = KeWaitForMultipleObjects(ThreadCount, ThreadObjects, WaitAny, Executive, KernelMode, FALSE, &ShortTimeout, WaitBlock); ok_eq_hex(Status, STATUS_TIMEOUT); } for (i = 0; i < ThreadCount; ++i) { ObDereferenceObject(Threads[i].Thread); Status = ZwClose(Threads[i].Handle); ok_eq_hex(Status, STATUS_SUCCESS); } }
static VOID TestEventFunctional( IN PKEVENT Event, IN EVENT_TYPE Type, IN KIRQL OriginalIrql) { LONG State; PKTHREAD Thread = KeGetCurrentThread(); memset(Event, 0x55, sizeof *Event); KeInitializeEvent(Event, Type, FALSE); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); memset(Event, 0x55, sizeof *Event); KeInitializeEvent(Event, Type, TRUE); CheckEvent(Event, Type, 1L, FALSE, OriginalIrql, (PVOID *)NULL, 0); Event->Header.SignalState = 0x12345678L; CheckEvent(Event, Type, 0x12345678L, FALSE, OriginalIrql, (PVOID *)NULL, 0); State = KePulseEvent(Event, 0, FALSE); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 0x12345678L); Event->Header.SignalState = 0x12345678L; KeClearEvent(Event); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); State = KeSetEvent(Event, 0, FALSE); CheckEvent(Event, Type, 1L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 0L); State = KeResetEvent(Event); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 1L); Event->Header.SignalState = 0x23456789L; State = KeSetEvent(Event, 0, FALSE); CheckEvent(Event, Type, 1L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 0x23456789L); Event->Header.SignalState = 0x3456789AL; State = KeResetEvent(Event); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 0x3456789AL); /* Irql is raised to DISPATCH_LEVEL here, which kills checked build, * a spinlock is acquired and never released, which kills MP build */ if ((OriginalIrql <= DISPATCH_LEVEL || !KmtIsCheckedBuild) && !KmtIsMultiProcessorBuild) { Event->Header.SignalState = 0x456789ABL; State = KeSetEvent(Event, 0, TRUE); CheckEvent(Event, Type, 1L, TRUE, DISPATCH_LEVEL, (PVOID *)NULL, 0); ok_eq_long(State, 0x456789ABL); ok_eq_uint(Thread->WaitIrql, OriginalIrql); /* repair the "damage" */ Thread->WaitNext = FALSE; KmtSetIrql(OriginalIrql); Event->Header.SignalState = 0x56789ABCL; State = KePulseEvent(Event, 0, TRUE); CheckEvent(Event, Type, 0L, TRUE, DISPATCH_LEVEL, (PVOID *)NULL, 0); ok_eq_long(State, 0x56789ABCL); ok_eq_uint(Thread->WaitIrql, OriginalIrql); /* repair the "damage" */ Thread->WaitNext = FALSE; KmtSetIrql(OriginalIrql); } ok_irql(OriginalIrql); KmtSetIrql(OriginalIrql); }
static VOID TestFastMutex( PFAST_MUTEX Mutex, KIRQL OriginalIrql) { PKTHREAD Thread = KeGetCurrentThread(); ok_irql(OriginalIrql); /* acquire/release normally */ ExAcquireFastMutex(Mutex); CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); ok_bool_false(ExTryToAcquireFastMutex(Mutex), "ExTryToAcquireFastMutex returned"); CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); ExReleaseFastMutex(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql); #ifdef _M_IX86 /* ntoskrnl's fastcall version */ ExiAcquireFastMutex(Mutex); CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); ok_bool_false(ExiTryToAcquireFastMutex(Mutex), "ExiTryToAcquireFastMutex returned"); CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); ExiReleaseFastMutex(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql); #endif /* try to acquire */ ok_bool_true(ExTryToAcquireFastMutex(Mutex), "ExTryToAcquireFastMutex returned"); CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); ExReleaseFastMutex(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql); /* shortcut functions with critical region */ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(Mutex); ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(Mutex); /* acquire/release unsafe */ if (!KmtIsCheckedBuild || OriginalIrql == APC_LEVEL) { ExAcquireFastMutexUnsafe(Mutex); CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, OriginalIrql); ExReleaseFastMutexUnsafe(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql); /* mismatched acquire/release */ ExAcquireFastMutex(Mutex); CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); ExReleaseFastMutexUnsafe(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, APC_LEVEL); KmtSetIrql(OriginalIrql); CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql); Mutex->OldIrql = 0x55555555LU; ExAcquireFastMutexUnsafe(Mutex); CheckMutex(Mutex, 0L, Thread, 0LU, 0x55555555LU, OriginalIrql); Mutex->OldIrql = PASSIVE_LEVEL; ExReleaseFastMutex(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, PASSIVE_LEVEL, PASSIVE_LEVEL); KmtSetIrql(OriginalIrql); CheckMutex(Mutex, 1L, NULL, 0LU, PASSIVE_LEVEL, OriginalIrql); } if (!KmtIsCheckedBuild) { /* release without acquire */ ExReleaseFastMutexUnsafe(Mutex); CheckMutex(Mutex, 2L, NULL, 0LU, PASSIVE_LEVEL, OriginalIrql); --Mutex->Count; Mutex->OldIrql = OriginalIrql; ExReleaseFastMutex(Mutex); CheckMutex(Mutex, 2L, NULL, 0LU, OriginalIrql, OriginalIrql); ExReleaseFastMutex(Mutex); CheckMutex(Mutex, 3L, NULL, 0LU, OriginalIrql, OriginalIrql); Mutex->Count -= 2; } /* make sure we survive this in case of error */ ok_eq_long(Mutex->Count, 1L); Mutex->Count = 1; ok_irql(OriginalIrql); KmtSetIrql(OriginalIrql); }