[PATCH 0/4] MR9941: ntoskrnl: Handle FileFsDeviceInformation.
From: Elizabeth Figura <zfigura@codeweavers.com> --- dlls/ntoskrnl.exe/tests/driver.c | 12 ++++++++++-- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index f30c340e9bd..ece4923dd06 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -2936,6 +2936,11 @@ static NTSTATUS WINAPI driver_QueryVolumeInformation(DEVICE_OBJECT *device, IRP return STATUS_PENDING; } + case FileFsDeviceInformation: + /* This one is actually handled by the I/O manager; + * it's never passed down to a driver. */ + todo_wine ok(0, "Unexpected call.\n"); + /* fall through */ default: ret = STATUS_NOT_IMPLEMENTED; break; @@ -3011,14 +3016,17 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry) RtlInitUnicodeString(&nameW, L"\\Device\\WineTestDriver"); RtlInitUnicodeString(&linkW, L"\\DosDevices\\WineTestDriver"); - status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &lower_device); + status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN, + FILE_DEVICE_SECURE_OPEN | FILE_FLOPPY_DISKETTE | FILE_PORTABLE_DEVICE, + FALSE, &lower_device); ok(!status, "failed to create device, status %#lx\n", status); status = IoCreateSymbolicLink(&linkW, &nameW); ok(!status, "failed to create link, status %#lx\n", status); lower_device->Flags &= ~DO_DEVICE_INITIALIZING; RtlInitUnicodeString(&nameW, L"\\Device\\WineTestUpper"); - status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &upper_device); + status = IoCreateDevice(driver, 16, &nameW, FILE_DEVICE_UNKNOWN, + FILE_DEVICE_SECURE_OPEN | FILE_READ_ONLY_DEVICE, FALSE, &upper_device); ok(!status, "failed to create device, status %#lx\n", status); IoAttachDeviceToDeviceStack(upper_device, lower_device); diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 0f0caf76132..944449ca859 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1187,6 +1187,7 @@ static void test_object_info(void) OBJECT_TYPE_INFORMATION *type_info = (OBJECT_TYPE_INFORMATION *)buffer; FILE_FS_VOLUME_INFORMATION *volume_info = (FILE_FS_VOLUME_INFORMATION *)buffer; FILE_NAME_INFORMATION *file_info = (FILE_NAME_INFORMATION *)buffer; + FILE_FS_DEVICE_INFORMATION device_info; HANDLE file; NTSTATUS status; IO_STATUS_BLOCK io; @@ -1208,6 +1209,26 @@ static void test_object_info(void) status = NtQueryVolumeInformationFile(device, &io, buffer, sizeof(buffer), FileFsVolumeInformation); todo_wine ok(status == STATUS_INVALID_DEVICE_REQUEST, "got %#lx\n", status); + io.Status = 0xdeadf00d; + io.Information = 0xdeadf00d; + status = NtQueryVolumeInformationFile(device, &io, &device_info, sizeof(device_info) - 1, FileFsDeviceInformation); + todo_wine ok(status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", status); + ok(io.Status == 0xdeadf00d, "got status %#lx\n", io.Status); + ok(io.Information == 0xdeadf00d, "got information %Iu\n", io.Information); + + io.Status = 0xdeadf00d; + io.Information = 0xdeadf00d; + status = NtQueryVolumeInformationFile(device, &io, &device_info, sizeof(device_info), FileFsDeviceInformation); + todo_wine ok(!status, "got %#lx\n", status); + todo_wine ok(!io.Status, "got status %#lx\n", io.Status); + todo_wine ok(io.Information == sizeof(FILE_FS_DEVICE_INFORMATION), "got information %Iu\n", io.Information); + if (!status) + { + ok(device_info.DeviceType == FILE_DEVICE_UNKNOWN, "Got type %#lx.\n", device_info.DeviceType); + ok(device_info.Characteristics == (FILE_DEVICE_SECURE_OPEN | FILE_FLOPPY_DISKETTE | FILE_PORTABLE_DEVICE), + "Got characteristics %#lx.\n", device_info.Characteristics); + } + file = CreateFileA("\\\\.\\WineTestDriver\\subfile", 0, 0, NULL, OPEN_EXISTING, 0, NULL); todo_wine ok(file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError()); if (file == INVALID_HANDLE_VALUE) return; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9941
From: Elizabeth Figura <zfigura@codeweavers.com> --- dlls/ntoskrnl.exe/tests/driver.c | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index ece4923dd06..aea0a0bd252 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -2444,6 +2444,49 @@ static void test_default_security(void) FltFreeSecurityDescriptor(sd); } +static void test_device_object(void) +{ + todo_wine ok(lower_device->Type == 3, "Got type %d.\n", lower_device->Type); + todo_wine ok(lower_device->ReferenceCount == 1, "Got refcount %ld.\n", lower_device->ReferenceCount); + ok(lower_device->DriverObject == driver_obj, "Got driver %p.\n", lower_device->DriverObject); + ok(!lower_device->NextDevice, "Got next device %p.\n", lower_device->NextDevice); + ok(lower_device->AttachedDevice == upper_device, "Got attached device %p.\n", lower_device->AttachedDevice); + ok(!lower_device->CurrentIrp, "Got current IRP %p.\n", lower_device->CurrentIrp); + ok(!lower_device->Timer, "Got timer %p.\n", lower_device->Timer); + todo_wine ok(lower_device->Flags == 0x40, "Got flags %#lx.\n", lower_device->Flags); + todo_wine ok(lower_device->Characteristics == (FILE_DEVICE_SECURE_OPEN | FILE_FLOPPY_DISKETTE | FILE_PORTABLE_DEVICE), + "Got characteristics %#lx.\n", lower_device->Characteristics); + ok(!lower_device->Vpb, "Got VPB %p.\n", lower_device->Vpb); + todo_wine ok(!lower_device->DeviceExtension, "Got extension %p.\n", lower_device->DeviceExtension); + ok(lower_device->DeviceType == FILE_DEVICE_UNKNOWN, "Got device type %#lx.\n", lower_device->DeviceType); + ok(lower_device->StackSize == 1, "Got stack size %u.\n", lower_device->StackSize); + ok(!lower_device->AlignmentRequirement, "Got alignment %lu.\n", lower_device->AlignmentRequirement); + ok(!lower_device->ActiveThreadCount, "Got thread count %lu.\n", lower_device->ActiveThreadCount); + ok(!lower_device->SectorSize, "Got sector size %u.\n", lower_device->SectorSize); + todo_wine ok(lower_device->Spare1 == 0x1, "Got Spare1 %#x.\n", lower_device->Spare1); + ok(!lower_device->Reserved, "Got Reserved %p.\n", lower_device->Reserved); + + todo_wine ok(upper_device->Type == 3, "Got type %d.\n", upper_device->Type); + ok(!upper_device->ReferenceCount, "Got refcount %ld.\n", upper_device->ReferenceCount); + ok(upper_device->DriverObject == driver_obj, "Got driver %p.\n", upper_device->DriverObject); + ok(upper_device->NextDevice == lower_device, "Got next device %p.\n", upper_device->NextDevice); + ok(!upper_device->AttachedDevice, "Got attached device %p.\n", upper_device->AttachedDevice); + todo_wine ok(!upper_device->CurrentIrp, "Got current IRP %p.\n", upper_device->CurrentIrp); + ok(!upper_device->Timer, "Got timer %p.\n", upper_device->Timer); + todo_wine ok(upper_device->Flags == 0x40, "Got flags %#lx.\n", upper_device->Flags); + todo_wine ok(upper_device->Characteristics == (FILE_DEVICE_SECURE_OPEN | FILE_READ_ONLY_DEVICE), + "Got characteristics %#lx.\n", upper_device->Characteristics); + ok(!upper_device->Vpb, "Got VPB %p.\n", upper_device->Vpb); + ok(!!upper_device->DeviceExtension, "Expected extension.\n"); + ok(upper_device->DeviceType == FILE_DEVICE_UNKNOWN, "Got device type %#lx.\n", upper_device->DeviceType); + ok(upper_device->StackSize == 2, "Got stack size %u.\n", upper_device->StackSize); + ok(!upper_device->AlignmentRequirement, "Got alignment %lu.\n", upper_device->AlignmentRequirement); + ok(!upper_device->ActiveThreadCount, "Got thread count %lu.\n", upper_device->ActiveThreadCount); + ok(!upper_device->SectorSize, "Got sector size %u.\n", upper_device->SectorSize); + ok(!upper_device->Spare1, "Got Spare1 %#x.\n", upper_device->Spare1); + ok(!upper_device->Reserved, "Got Reserved %p.\n", upper_device->Reserved); +} + static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack) { void *buffer = irp->AssociatedIrp.SystemBuffer; @@ -2489,6 +2532,7 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st test_permanence(); test_driver_object_extension(); test_default_security(); + test_device_object(); IoMarkIrpPending(irp); IoQueueWorkItem(work_item, main_test_task, DelayedWorkQueue, irp); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9941
From: Elizabeth Figura <zfigura@codeweavers.com> --- dlls/ntoskrnl.exe/ntoskrnl.c | 1 + dlls/ntoskrnl.exe/tests/driver.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index b3f45751b99..92dbfe7a282 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -1646,6 +1646,7 @@ NTSTATUS WINAPI IoCreateDevice( DRIVER_OBJECT *driver, ULONG ext_size, device = &wine_device->device_obj; device->DriverObject = driver; + device->Characteristics = characteristics; device->DeviceExtension = wine_device + 1; device->DeviceType = type; device->StackSize = 1; diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index aea0a0bd252..76f7fd8d116 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -2454,7 +2454,7 @@ static void test_device_object(void) ok(!lower_device->CurrentIrp, "Got current IRP %p.\n", lower_device->CurrentIrp); ok(!lower_device->Timer, "Got timer %p.\n", lower_device->Timer); todo_wine ok(lower_device->Flags == 0x40, "Got flags %#lx.\n", lower_device->Flags); - todo_wine ok(lower_device->Characteristics == (FILE_DEVICE_SECURE_OPEN | FILE_FLOPPY_DISKETTE | FILE_PORTABLE_DEVICE), + ok(lower_device->Characteristics == (FILE_DEVICE_SECURE_OPEN | FILE_FLOPPY_DISKETTE | FILE_PORTABLE_DEVICE), "Got characteristics %#lx.\n", lower_device->Characteristics); ok(!lower_device->Vpb, "Got VPB %p.\n", lower_device->Vpb); todo_wine ok(!lower_device->DeviceExtension, "Got extension %p.\n", lower_device->DeviceExtension); @@ -2474,7 +2474,7 @@ static void test_device_object(void) todo_wine ok(!upper_device->CurrentIrp, "Got current IRP %p.\n", upper_device->CurrentIrp); ok(!upper_device->Timer, "Got timer %p.\n", upper_device->Timer); todo_wine ok(upper_device->Flags == 0x40, "Got flags %#lx.\n", upper_device->Flags); - todo_wine ok(upper_device->Characteristics == (FILE_DEVICE_SECURE_OPEN | FILE_READ_ONLY_DEVICE), + ok(upper_device->Characteristics == (FILE_DEVICE_SECURE_OPEN | FILE_READ_ONLY_DEVICE), "Got characteristics %#lx.\n", upper_device->Characteristics); ok(!upper_device->Vpb, "Got VPB %p.\n", upper_device->Vpb); ok(!!upper_device->DeviceExtension, "Expected extension.\n"); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9941
From: Elizabeth Figura <zfigura@codeweavers.com> --- dlls/ntoskrnl.exe/ntoskrnl.c | 30 ++++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/tests/driver.c | 2 +- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 17 +++++++---------- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 92dbfe7a282..d74feb8ae90 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -514,6 +514,7 @@ struct dispatch_context static NTSTATUS dispatch_irp( DEVICE_OBJECT *device, IRP *irp, struct dispatch_context *context ) { + IO_STACK_LOCATION *irpsp = IoGetNextIrpStackLocation( irp ); struct irp_data *irp_data; LARGE_INTEGER count; NTSTATUS status; @@ -529,6 +530,35 @@ static NTSTATUS dispatch_irp( DEVICE_OBJECT *device, IRP *irp, struct dispatch_c context->irp_data = irp_data; context->handle = 0; + if (irpsp->MajorFunction == IRP_MJ_QUERY_VOLUME_INFORMATION + && irpsp->Parameters.QueryVolume.FsInformationClass == FileFsDeviceInformation) + { + /* Handled by us; never passed to the driver. */ + DEVICE_OBJECT *bottom_device = irp->Tail.Overlay.OriginalFileObject->DeviceObject; + NTSTATUS status; + + --irp->CurrentLocation; + --irp->Tail.Overlay.CurrentStackLocation; + + if (irpsp->Parameters.QueryVolume.Length >= sizeof(FILE_FS_DEVICE_INFORMATION)) + { + FILE_FS_DEVICE_INFORMATION *info = irp->AssociatedIrp.SystemBuffer; + + info->DeviceType = bottom_device->DeviceType; + info->Characteristics = bottom_device->Characteristics; + irp->IoStatus.Information = sizeof(*info); + status = STATUS_SUCCESS; + } + else + { + status = STATUS_INFO_LENGTH_MISMATCH; + } + + irp->IoStatus.Status = status; + IoCompleteRequest( irp, IO_NO_INCREMENT ); + return status; + } + KeQueryTickCount( &count ); /* update the global KeTickCount */ device->CurrentIrp = irp; diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 76f7fd8d116..9358cf605a4 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -2983,7 +2983,7 @@ static NTSTATUS WINAPI driver_QueryVolumeInformation(DEVICE_OBJECT *device, IRP case FileFsDeviceInformation: /* This one is actually handled by the I/O manager; * it's never passed down to a driver. */ - todo_wine ok(0, "Unexpected call.\n"); + ok(0, "Unexpected call.\n"); /* fall through */ default: ret = STATUS_NOT_IMPLEMENTED; diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 944449ca859..06279b1c49e 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1212,22 +1212,19 @@ static void test_object_info(void) io.Status = 0xdeadf00d; io.Information = 0xdeadf00d; status = NtQueryVolumeInformationFile(device, &io, &device_info, sizeof(device_info) - 1, FileFsDeviceInformation); - todo_wine ok(status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", status); + ok(status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", status); ok(io.Status == 0xdeadf00d, "got status %#lx\n", io.Status); ok(io.Information == 0xdeadf00d, "got information %Iu\n", io.Information); io.Status = 0xdeadf00d; io.Information = 0xdeadf00d; status = NtQueryVolumeInformationFile(device, &io, &device_info, sizeof(device_info), FileFsDeviceInformation); - todo_wine ok(!status, "got %#lx\n", status); - todo_wine ok(!io.Status, "got status %#lx\n", io.Status); - todo_wine ok(io.Information == sizeof(FILE_FS_DEVICE_INFORMATION), "got information %Iu\n", io.Information); - if (!status) - { - ok(device_info.DeviceType == FILE_DEVICE_UNKNOWN, "Got type %#lx.\n", device_info.DeviceType); - ok(device_info.Characteristics == (FILE_DEVICE_SECURE_OPEN | FILE_FLOPPY_DISKETTE | FILE_PORTABLE_DEVICE), - "Got characteristics %#lx.\n", device_info.Characteristics); - } + ok(!status, "got %#lx\n", status); + ok(!io.Status, "got status %#lx\n", io.Status); + ok(io.Information == sizeof(FILE_FS_DEVICE_INFORMATION), "got information %Iu\n", io.Information); + ok(device_info.DeviceType == FILE_DEVICE_UNKNOWN, "Got type %#lx.\n", device_info.DeviceType); + ok(device_info.Characteristics == (FILE_DEVICE_SECURE_OPEN | FILE_FLOPPY_DISKETTE | FILE_PORTABLE_DEVICE), + "Got characteristics %#lx.\n", device_info.Characteristics); file = CreateFileA("\\\\.\\WineTestDriver\\subfile", 0, 0, NULL, OPEN_EXISTING, 0, NULL); todo_wine ok(file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError()); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9941
Do we really want to do that in the middle of `dispatch_irp`? What if there are other such cases? Also could you please try to follow the indentation style of the existing code? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9941#note_127715
Do we really want to do that in the middle of `dispatch_irp`? What if there are other such cases?
I thought about doing it in a few different ways, and this seemed the most attractive—it allows us to implement the IRP the same way we'd implement any other one, and put all of the logic in one place. It certainly seemed the easiest code to follow. If this is ugly, I guess I'll try a different approach, probably doing it early in dispatch_volume() and altering the main loop to handle requests that have an irp_data but no actual irp? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9941#note_127717
I think early in dispatch_volume() would be cleaner, yes. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9941#note_127952
participants (3)
-
Alexandre Julliard (@julliard) -
Elizabeth Figura -
Elizabeth Figura (@zfigura)