From: Bernhard Übelacker bernhardu@mailbox.org
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51770 --- dlls/kernel32/tests/volume.c | 117 +++++++++++++++++++++++++++++++++++ dlls/ntdll/unix/file.c | 14 +++++ 2 files changed, 131 insertions(+)
diff --git a/dlls/kernel32/tests/volume.c b/dlls/kernel32/tests/volume.c index 5d2d971232f..3283c680897 100644 --- a/dlls/kernel32/tests/volume.c +++ b/dlls/kernel32/tests/volume.c @@ -659,6 +659,122 @@ static void test_disk_query_property(void) CloseHandle(handle); }
+static void test_disk_get_device_number(void) +{ + STORAGE_DEVICE_NUMBER device_number = {0}; + HANDLE handle; + DWORD error; + DWORD size; + BOOL ret; + IO_STATUS_BLOCK io; + NTSTATUS status; + + handle = CreateFileA("\\.\PhysicalDrive0", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + 0, 0); + if (handle == INVALID_HANDLE_VALUE) + { + win_skip("can't open \\.\PhysicalDrive0 %#lx\n", GetLastError()); + return; + } + + /* DeviceIoControl */ + SetLastError(0xdeadbeef); + ret = DeviceIoControl(handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &device_number, sizeof(device_number), &size, NULL); + error = GetLastError(); + ok(ret, "expect ret %#x, got %#x\n", TRUE, ret); + ok(error == 0xdeadbeef, "expect err %#x, got err %#lx\n", 0xdeadbeef, error); + ok(size == sizeof(device_number), "got size %ld\n", size); + + SetLastError(0xdeadbeef); + ret = DeviceIoControl(handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 4, &device_number, sizeof(device_number), &size, NULL); + error = GetLastError(); + ok(ret, "expect ret %#x, got %#x\n", TRUE, ret); + ok(error == 0xdeadbeef, "expect err %#x, got err %#lx\n", 0xdeadbeef, error); + ok(size == sizeof(device_number), "got size %ld\n", size); + + SetLastError(0xdeadbeef); + ret = DeviceIoControl(handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, (LPVOID)0xdeadbeef, 4, &device_number, sizeof(device_number), &size, NULL); + error = GetLastError(); + ok(!ret, "expect ret %#x, got %#x\n", FALSE, ret); + ok(error == ERROR_NOACCESS, "expect err %#x, got err %#lx\n", 0xdeadbeef, error); + ok(size == sizeof(device_number), "got size %ld\n", size); + + SetLastError(0xdeadbeef); + ret = DeviceIoControl(handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, &device_number, sizeof(device_number), &device_number, sizeof(device_number), &size, NULL); + error = GetLastError(); + ok(ret, "expect ret %#x, got %#x\n", TRUE, ret); + ok(error == 0xdeadbeef, "expect err %#x, got err %#lx\n", 0xdeadbeef, error); + ok(size == sizeof(device_number), "got size %ld\n", size); + + /* NtDeviceIoControlFile */ + io.Status = 0xdeadf00d; + io.Information = 0xdeadf00d; + status = NtDeviceIoControlFile(handle, NULL, NULL, NULL, &io, + IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &device_number, sizeof(device_number)); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + ok(io.Status == STATUS_SUCCESS, "got status %#lx\n", io.Status); + ok(io.Information == sizeof(device_number), "got information %#Ix\n", io.Information); + + io.Status = 0xdeadf00d; + io.Information = 0xdeadf00d; + status = NtDeviceIoControlFile(handle, NULL, NULL, NULL, &io, + IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 4, &device_number, sizeof(device_number)); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + ok(io.Status == STATUS_SUCCESS, "got status %#lx\n", io.Status); + ok(io.Information == sizeof(device_number), "got information %#Ix\n", io.Information); + + io.Status = 0xdeadf00d; + io.Information = 0xdeadf00d; + status = NtDeviceIoControlFile(handle, NULL, NULL, NULL, &io, + IOCTL_STORAGE_GET_DEVICE_NUMBER, (LPVOID)0xdeadbeef, 4, &device_number, sizeof(device_number)); + ok(status == STATUS_ACCESS_VIOLATION, "got %#lx\n", status); + ok(io.Status == 0xdeadf00d, "got status %#lx\n", io.Status); + ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information); + + io.Status = 0xdeadf00d; + io.Information = 0xdeadf00d; + status = NtDeviceIoControlFile(handle, NULL, NULL, NULL, &io, + IOCTL_STORAGE_GET_DEVICE_NUMBER, &device_number, sizeof(device_number), &device_number, sizeof(device_number)); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + ok(io.Status == STATUS_SUCCESS, "got status %#lx\n", io.Status); + ok(io.Information == sizeof(device_number), "got information %#Ix\n", io.Information); + + /* NtFsControlFile */ + io.Status = 0xdeadf00d; + io.Information = 0xdeadf00d; + status = NtFsControlFile(handle, NULL, NULL, NULL, &io, + IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &device_number, sizeof(device_number)); + ok(status == STATUS_INVALID_PARAMETER, "got %#lx\n", status); + ok(io.Status == 0xdeadf00d, "got status %#lx\n", io.Status); + ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information); + + io.Status = 0xdeadf00d; + io.Information = 0xdeadf00d; + status = NtFsControlFile(handle, NULL, NULL, NULL, &io, + IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 4, &device_number, sizeof(device_number)); + ok(status == STATUS_INVALID_PARAMETER, "got %#lx\n", status); + ok(io.Status == 0xdeadf00d, "got status %#lx\n", io.Status); + ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information); + + io.Status = 0xdeadf00d; + io.Information = 0xdeadf00d; + status = NtFsControlFile(handle, NULL, NULL, NULL, &io, + IOCTL_STORAGE_GET_DEVICE_NUMBER, (LPVOID)0xdeadbeef, 4, &device_number, sizeof(device_number)); + ok(status == STATUS_ACCESS_VIOLATION, "got %#lx\n", status); + ok(io.Status == 0xdeadf00d, "got status %#lx\n", io.Status); + ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information); + + io.Status = 0xdeadf00d; + io.Information = 0xdeadf00d; + status = NtFsControlFile(handle, NULL, NULL, NULL, &io, + IOCTL_STORAGE_GET_DEVICE_NUMBER, &device_number, sizeof(device_number), &device_number, sizeof(device_number)); + ok(status == STATUS_INVALID_PARAMETER, "got %#lx\n", status); + ok(io.Status == 0xdeadf00d, "got status %#lx\n", io.Status); + ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information); + + CloseHandle(handle); +} + static void test_GetVolumePathNameA(void) { char volume_path[MAX_PATH], cwd[MAX_PATH], expect_path[MAX_PATH]; @@ -1731,6 +1847,7 @@ START_TEST(volume) test_enum_vols(); test_disk_extents(); test_disk_query_property(); + test_disk_get_device_number(); test_GetVolumePathNamesForVolumeNameA(); test_GetVolumePathNamesForVolumeNameW(); test_cdrom_ioctl(); diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index ff1618f31fd..aae76df16ac 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -5956,6 +5956,15 @@ NTSTATUS WINAPI NtDeviceIoControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUT if (HandleToLong( handle ) == ~0) return STATUS_INVALID_HANDLE;
+ if (code == IOCTL_STORAGE_GET_DEVICE_NUMBER) { + if (!in_buffer) { + in_size = 0; + } else { + if (!virtual_check_buffer_for_read( in_buffer, in_size )) + return STATUS_ACCESS_VIOLATION; + } + } + switch (device) { case FILE_DEVICE_BEEP: @@ -6033,6 +6042,11 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
switch (code) { + case IOCTL_STORAGE_GET_DEVICE_NUMBER: + if (in_buffer && !virtual_check_buffer_for_read( in_buffer, in_size )) + return STATUS_ACCESS_VIOLATION; + return STATUS_INVALID_PARAMETER; + case FSCTL_DISMOUNT_VOLUME: status = server_ioctl_file( handle, event, apc, apc_context, io, code, in_buffer, in_size, out_buffer, out_size );