From: Bernhard Übelacker bernhardu@mailbox.org
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51770 --- dlls/ntdll/unix/file.c | 14 ++++++++++++++ dlls/ntoskrnl.exe/tests/ntoskrnl.c | 12 ++++++------ 2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index c6533710365..ad04c8c7ce6 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -5985,6 +5985,7 @@ NTSTATUS WINAPI NtDeviceIoControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUT void *out_buffer, ULONG out_size ) { ULONG device = (code >> 16); + ULONG method = (code & 3); NTSTATUS status = STATUS_NOT_SUPPORTED;
TRACE( "(%p,%p,%p,%p,%p,0x%08x,%p,0x%08x,%p,0x%08x)\n", @@ -5996,6 +5997,19 @@ NTSTATUS WINAPI NtDeviceIoControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUT if (HandleToLong( handle ) == ~0) return STATUS_INVALID_HANDLE;
+ switch (method) + { + case METHOD_BUFFERED: + case METHOD_IN_DIRECT: + case METHOD_OUT_DIRECT: + if (in_buffer && in_size && !virtual_check_buffer_for_read(in_buffer, in_size)) return STATUS_ACCESS_VIOLATION; + if ((out_buffer || method != METHOD_BUFFERED) && out_size && !virtual_check_buffer_for_write(out_buffer, out_size)) + return STATUS_ACCESS_VIOLATION; + if (!in_buffer && in_size) in_size = 0; + if (!out_buffer && out_size) out_size = 0; + break; + } + switch (device) { case FILE_DEVICE_BEEP: diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 3f16b69a3b6..6a02de7a11a 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1168,13 +1168,13 @@ static void test_ioctl_buffers(void) } param_tests[] = { - {NULL, 0, NULL, 0, STATUS_END_OF_FILE, STATUS_END_OF_FILE, STATUS_END_OF_FILE, {0, 1, 1, 0}}, - {NULL, 4, NULL, 0, STATUS_END_OF_FILE, STATUS_END_OF_FILE, STATUS_INVALID_PARAMETER_2, {1, 1, 1, 1}}, - {(void *)16, 0, NULL, 0, STATUS_END_OF_FILE, STATUS_END_OF_FILE, STATUS_INVALID_PARAMETER_1, {0, 1, 1, 1}}, + {NULL, 0, NULL, 0, STATUS_END_OF_FILE, STATUS_END_OF_FILE, STATUS_END_OF_FILE, {0, 0, 0, 0}}, + {NULL, 4, NULL, 0, STATUS_END_OF_FILE, STATUS_END_OF_FILE, STATUS_INVALID_PARAMETER_2, {0, 0, 0, 1}}, + {(void *)16, 0, NULL, 0, STATUS_END_OF_FILE, STATUS_END_OF_FILE, STATUS_INVALID_PARAMETER_1, {0, 0, 0, 1}}, {(void *)16, 4, NULL, 0, STATUS_ACCESS_VIOLATION, STATUS_ACCESS_VIOLATION, STATUS_INVALID_PARAMETER_1, {0, 0, 0, 1}}, - {NULL, 0, NULL, 4, STATUS_END_OF_FILE, STATUS_ACCESS_VIOLATION, STATUS_INVALID_PARAMETER_4, {1, 1, 1, 1}}, - {NULL, 0, (void *)16, 0, STATUS_END_OF_FILE, STATUS_END_OF_FILE, STATUS_INVALID_PARAMETER_3, {0, 1, 1, 1}}, - {NULL, 0, (void *)16, 4, STATUS_ACCESS_VIOLATION, STATUS_ACCESS_VIOLATION, STATUS_INVALID_PARAMETER_3, {1, 1, 1, 1}}, + {NULL, 0, NULL, 4, STATUS_END_OF_FILE, STATUS_ACCESS_VIOLATION, STATUS_INVALID_PARAMETER_4, {0, 0, 0, 1}}, + {NULL, 0, (void *)16, 0, STATUS_END_OF_FILE, STATUS_END_OF_FILE, STATUS_INVALID_PARAMETER_3, {0, 0, 0, 1}}, + {NULL, 0, (void *)16, 4, STATUS_ACCESS_VIOLATION, STATUS_ACCESS_VIOLATION, STATUS_INVALID_PARAMETER_3, {0, 0, 0, 1}}, };
for (j = 0; j < ARRAY_SIZE(param_tests); ++j)