Previously it was assumed that synchronous I/O fills the 64-bit IOSB, and asynchronous I/O fills the 32-bit IOSB.
As the ntdll:wow64 tests show, this is incorrect. I/O on an overlapped handle, whether it is synchronous or not, fills the 32-bit IOSB, and I/O on a non-overlapped handle always fills the 64-bit IOSB.
The first half is important, since completion can be signaled before we even return from the initial I/O call [NtReadFile() etc.] Filling the IOSB after signaling completion is the cause of bug 56389. This patch series fixes that.
The second discrepancy does not cause any bugs, as far as I can see, and is a bit harder to fix anyway. It is therefore not addressed by this patch series.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56389
-- v2: ntdll: Always fill the 32-bit iosb for overlapped handles, for regular read/write. ntdll: Always fill the 32-bit iosb for overlapped handles, in set_async_direct_result(). ntdll: Always fill the 32-bit iosb for overlapped handles, in file_complete_async().
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ntdll/unix/file.c | 37 +++++++++++++++++----------------- dlls/ntdll/unix/process.c | 4 +--- dlls/ntdll/unix/unix_private.h | 2 ++ 3 files changed, 22 insertions(+), 21 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 2ce38b34158..87afc20c48d 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -2268,7 +2268,6 @@ static NTSTATUS get_mountmgr_fs_info( HANDLE handle, int fd, struct mountmgr_uni OBJECT_ATTRIBUTES attr; UNICODE_STRING string; char *unix_name; - IO_STATUS_BLOCK io = {{0}}; HANDLE mountmgr; unsigned int status; int letter; @@ -2294,8 +2293,7 @@ static NTSTATUS get_mountmgr_fs_info( HANDLE handle, int fd, struct mountmgr_uni FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT ); if (status) return status;
- status = NtDeviceIoControlFile( mountmgr, NULL, NULL, NULL, &io, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE, - drive, sizeof(*drive), drive, size ); + status = sync_ioctl( mountmgr, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE, drive, sizeof(*drive), drive, size ); NtClose( mountmgr ); if (status == STATUS_BUFFER_OVERFLOW) status = STATUS_SUCCESS; else if (status) WARN("failed to retrieve filesystem type from mountmgr, status %#x\n", status); @@ -5321,8 +5319,6 @@ struct io_timeouts static unsigned int get_io_timeouts( HANDLE handle, enum server_fd_type type, ULONG count, BOOL is_read, struct io_timeouts *timeouts ) { - unsigned int status = STATUS_SUCCESS; - timeouts->interval = timeouts->total = -1;
switch(type) @@ -5331,11 +5327,9 @@ static unsigned int get_io_timeouts( HANDLE handle, enum server_fd_type type, UL { /* GetCommTimeouts */ SERIAL_TIMEOUTS st; - IO_STATUS_BLOCK io = {{0}};
- status = NtDeviceIoControlFile( handle, NULL, NULL, NULL, &io, - IOCTL_SERIAL_GET_TIMEOUTS, NULL, 0, &st, sizeof(st) ); - if (status) break; + if (sync_ioctl( handle, IOCTL_SERIAL_GET_TIMEOUTS, NULL, 0, &st, sizeof(st) )) + break;
if (is_read) { @@ -5370,8 +5364,7 @@ static unsigned int get_io_timeouts( HANDLE handle, enum server_fd_type type, UL { req->handle = wine_server_obj_handle( handle ); req->flags = 0; - if (!(status = wine_server_call( req )) && - reply->read_timeout != TIMEOUT_INFINITE) + if (!wine_server_call( req ) && reply->read_timeout != TIMEOUT_INFINITE) timeouts->total = reply->read_timeout / -10000; } SERVER_END_REQ; @@ -5418,14 +5411,13 @@ static NTSTATUS get_io_avail_mode( HANDLE handle, enum server_fd_type type, BOOL { /* GetCommTimeouts */ SERIAL_TIMEOUTS st; - IO_STATUS_BLOCK io = {{0}};
- status = NtDeviceIoControlFile( handle, NULL, NULL, NULL, &io, - IOCTL_SERIAL_GET_TIMEOUTS, NULL, 0, &st, sizeof(st) ); - if (status) break; - *avail_mode = (!st.ReadTotalTimeoutMultiplier && - !st.ReadTotalTimeoutConstant && - st.ReadIntervalTimeout == MAXDWORD); + if (!(status = sync_ioctl( handle, IOCTL_SERIAL_GET_TIMEOUTS, NULL, 0, &st, sizeof(st) ))) + { + *avail_mode = (!st.ReadTotalTimeoutMultiplier && + !st.ReadTotalTimeoutConstant && + st.ReadIntervalTimeout == MAXDWORD); + } break; } case FD_TYPE_MAILSLOT: @@ -6182,6 +6174,15 @@ NTSTATUS WINAPI NtDeviceIoControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUT }
+/* helper for internal ioctl calls */ +NTSTATUS sync_ioctl( HANDLE file, ULONG code, void *in_buffer, ULONG in_size, void *out_buffer, ULONG out_size ) +{ + IO_STATUS_BLOCK io; + + return NtDeviceIoControlFile( file, NULL, NULL, NULL, &io, code, in_buffer, in_size, out_buffer, out_size ); +} + + /* Tell Valgrind to ignore any holes in structs we will be passing to the * server */ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer, ULONG in_size ) diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index cc2d820e723..1815b46b0fc 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -413,9 +413,7 @@ static void set_stdio_fd( int stdin_fd, int stdout_fd ) */ static BOOL is_unix_console_handle( HANDLE handle ) { - IO_STATUS_BLOCK io = {{0}}; - return !NtDeviceIoControlFile( handle, NULL, NULL, NULL, &io, IOCTL_CONDRV_IS_UNIX, - NULL, 0, NULL, 0 ); + return !sync_ioctl( handle, IOCTL_CONDRV_IS_UNIX, NULL, 0, NULL, 0 ); }
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index c00b0e4b602..232f97490a1 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -312,6 +312,8 @@ extern NTSTATUS set_thread_wow64_context( HANDLE handle, const void *ctx, ULONG extern void fill_vm_counters( VM_COUNTERS_EX *pvmi, int unix_pid ); extern NTSTATUS open_hkcu_key( const char *path, HANDLE *key );
+extern NTSTATUS sync_ioctl( HANDLE file, ULONG code, void *in_buffer, ULONG in_size, + void *out_buffer, ULONG out_size ); extern NTSTATUS cdrom_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, IO_STATUS_BLOCK *io, UINT code, void *in_buffer, UINT in_size, void *out_buffer, UINT out_size );
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ntdll/unix/file.c | 3 +++ dlls/ntdll/unix/unix_private.h | 16 +++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 87afc20c48d..8415478c046 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -6177,8 +6177,11 @@ NTSTATUS WINAPI NtDeviceIoControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUT /* helper for internal ioctl calls */ NTSTATUS sync_ioctl( HANDLE file, ULONG code, void *in_buffer, ULONG in_size, void *out_buffer, ULONG out_size ) { + IO_STATUS_BLOCK32 io32; IO_STATUS_BLOCK io;
+ /* the 32-bit iosb is filled for overlapped file handles */ + io.Pointer = &io32; return NtDeviceIoControlFile( file, NULL, NULL, NULL, &io, code, in_buffer, in_size, out_buffer, out_size ); }
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 232f97490a1..2e0477e42e0 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -31,6 +31,16 @@
struct msghdr;
+typedef struct +{ + union + { + NTSTATUS Status; + ULONG Pointer; + }; + ULONG Information; +} IO_STATUS_BLOCK32; + #ifdef __i386__ static const WORD current_machine = IMAGE_FILE_MACHINE_I386; #elif defined(__x86_64__) @@ -462,11 +472,7 @@ static inline void set_async_iosb( client_ptr_t iosb, NTSTATUS status, ULONG_PTR
if (in_wow64_call()) { - struct iosb32 - { - NTSTATUS Status; - ULONG Information; - } *io = wine_server_get_ptr( iosb ); + IO_STATUS_BLOCK32 *io = wine_server_get_ptr( iosb ); io->Information = info; WriteRelease( &io->Status, status ); }
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ntdll/tests/wow64.c | 8 ++------ dlls/ntdll/unix/file.c | 31 +++++++++++++++++++------------ 2 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/dlls/ntdll/tests/wow64.c b/dlls/ntdll/tests/wow64.c index f5fbf6fd432..8c7d2507ebe 100644 --- a/dlls/ntdll/tests/wow64.c +++ b/dlls/ntdll/tests/wow64.c @@ -2211,16 +2211,12 @@ static void test_iosb(void)
status = call_func64( read_func, ARRAY_SIZE(args), args ); ok( status == STATUS_SUCCESS, "NtReadFile returned %lx\n", status ); - todo_wine - { ok( iosb32.Status == STATUS_SUCCESS, "status changed to %lx\n", iosb32.Status ); ok( iosb32.Information == sizeof("data"), "info changed to %lx\n", iosb32.Information ); ok( iosb64.Pointer == PtrToUlong(&iosb32), "pointer changed to %I64x\n", iosb64.Pointer ); ok( iosb64.Information == 0xdeadbeef, "info changed to %Ix\n", (ULONG_PTR)iosb64.Information ); - if (iosb32.Information == sizeof("data")) - ok( !memcmp( buffer, "data", iosb32.Information ), - "got wrong data %s\n", debugstr_an(buffer, iosb32.Information) ); - } + ok( !memcmp( buffer, "data", iosb32.Information ), + "got wrong data %s\n", debugstr_an(buffer, iosb32.Information) );
/* syscalls which are always synchronous set iosb64 but not iosb32 */
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 8415478c046..4f0fe685d88 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -5186,6 +5186,22 @@ static BOOL async_write_proc( void *user, ULONG_PTR *info, unsigned int *status return TRUE; }
+static void set_sync_iosb( IO_STATUS_BLOCK *io, NTSTATUS status, ULONG_PTR info, unsigned int options ) +{ + if (in_wow64_call() && !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))) + { + IO_STATUS_BLOCK32 *io32 = io->Pointer; + + io32->Status = status; + io32->Information = info; + } + else + { + io->Status = status; + io->Information = info; + } +} + /* do a read call through the server */ static unsigned int server_read_file( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_context, IO_STATUS_BLOCK *io, void *buffer, ULONG size, @@ -5211,10 +5227,7 @@ static unsigned int server_read_file( HANDLE handle, HANDLE event, PIO_APC_ROUTI wait_handle = wine_server_ptr_handle( reply->wait ); options = reply->options; if (wait_handle && status != STATUS_PENDING) - { - io->Status = status; - io->Information = wine_server_reply_size( reply ); - } + set_sync_iosb( io, status, wine_server_reply_size( reply ), options ); } SERVER_END_REQ;
@@ -5249,10 +5262,7 @@ static unsigned int server_write_file( HANDLE handle, HANDLE event, PIO_APC_ROUT wait_handle = wine_server_ptr_handle( reply->wait ); options = reply->options; if (wait_handle && status != STATUS_PENDING) - { - io->Status = status; - io->Information = reply->size; - } + set_sync_iosb( io, status, reply->size, options ); } SERVER_END_REQ;
@@ -5290,10 +5300,7 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event, wait_handle = wine_server_ptr_handle( reply->wait ); options = reply->options; if (wait_handle && status != STATUS_PENDING) - { - io->Status = status; - io->Information = wine_server_reply_size( reply ); - } + set_sync_iosb( io, status, wine_server_reply_size( reply ), options ); } SERVER_END_REQ;
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ntdll/unix/cdrom.c | 5 +++-- dlls/ntdll/unix/file.c | 16 +++++++++++----- dlls/ntdll/unix/serial.c | 5 +++-- dlls/ntdll/unix/socket.c | 35 +++++++++++++++++++++++----------- dlls/ntdll/unix/tape.c | 5 +++-- dlls/ntdll/unix/unix_private.h | 2 +- 6 files changed, 45 insertions(+), 23 deletions(-)
diff --git a/dlls/ntdll/unix/cdrom.c b/dlls/ntdll/unix/cdrom.c index c92ccc1185d..9e651414e9a 100644 --- a/dlls/ntdll/unix/cdrom.c +++ b/dlls/ntdll/unix/cdrom.c @@ -2819,10 +2819,11 @@ NTSTATUS cdrom_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE apc DWORD sz = 0; NTSTATUS status = STATUS_SUCCESS; int fd, needs_close, dev = 0; + unsigned int options;
TRACE( "%p %s %p %d %p %d %p\n", device, iocodex(code), in_buffer, in_size, out_buffer, out_size, io );
- if ((status = server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL ))) + if ((status = server_get_unix_fd( device, 0, &fd, &needs_close, NULL, &options ))) return status;
if ((status = CDROM_Open(fd, &dev))) @@ -3113,6 +3114,6 @@ NTSTATUS cdrom_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE apc } if (needs_close) close( fd ); if (!NT_ERROR(status)) - file_complete_async( device, event, apc, apc_user, io, status, sz ); + file_complete_async( device, options, event, apc, apc_user, io, status, sz ); return status; } diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 4f0fe685d88..2ab04040258 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -5515,13 +5515,12 @@ void set_async_direct_result( HANDLE *async_handle, IO_STATUS_BLOCK *io, }
/* complete async file I/O, signaling completion in all ways necessary */ -void file_complete_async( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, +void file_complete_async( HANDLE handle, unsigned int options, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, IO_STATUS_BLOCK *io, NTSTATUS status, ULONG_PTR information ) { ULONG_PTR iosb_ptr = iosb_client_ptr(io);
- io->Status = status; - io->Information = information; + set_sync_iosb( io, status, information, options ); if (event) NtSetEvent( event, NULL ); if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc, (ULONG_PTR)apc_user, iosb_ptr, 0 ); else if (apc_user) add_completion( handle, (ULONG_PTR)apc_user, status, information, FALSE ); @@ -6119,7 +6118,7 @@ NTSTATUS WINAPI NtWriteFileGather( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap if (needs_close) close( unix_handle ); if (status == STATUS_SUCCESS) { - file_complete_async( file, event, apc, apc_user, io, status, total ); + file_complete_async( file, options, event, apc, apc_user, io, status, total ); TRACE("= SUCCESS (%u)\n", total); } else @@ -6224,6 +6223,8 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap IO_STATUS_BLOCK *io, ULONG code, void *in_buffer, ULONG in_size, void *out_buffer, ULONG out_size ) { + unsigned int options; + int fd, needs_close; ULONG_PTR size = 0; NTSTATUS status;
@@ -6233,6 +6234,11 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
if (!io) return STATUS_INVALID_PARAMETER;
+ status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, &options ); + if (status && status != STATUS_BAD_DEVICE_TYPE) + return status; + if (needs_close) close( fd ); + ignore_server_ioctl_struct_holes( code, in_buffer, in_size );
switch (code) @@ -6318,7 +6324,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap }
if (!NT_ERROR(status) && status != STATUS_PENDING) - file_complete_async( handle, event, apc, apc_context, io, status, size ); + file_complete_async( handle, options, event, apc, apc_context, io, status, size ); return status; }
diff --git a/dlls/ntdll/unix/serial.c b/dlls/ntdll/unix/serial.c index 8637dfbd447..89b12980df7 100644 --- a/dlls/ntdll/unix/serial.c +++ b/dlls/ntdll/unix/serial.c @@ -1245,6 +1245,7 @@ NTSTATUS serial_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE ap NTSTATUS status = STATUS_SUCCESS; int fd = -1, needs_close = 0; enum server_fd_type type; + unsigned int options;
TRACE("%p %s %p %d %p %d %p\n", device, iocode2str(code), in_buffer, in_size, out_buffer, out_size, io); @@ -1259,7 +1260,7 @@ NTSTATUS serial_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE ap return STATUS_NOT_SUPPORTED; }
- if ((status = server_get_unix_fd( device, access, &fd, &needs_close, &type, NULL ))) + if ((status = server_get_unix_fd( device, access, &fd, &needs_close, &type, &options ))) return status; if (type != FD_TYPE_SERIAL) { @@ -1455,7 +1456,7 @@ NTSTATUS serial_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE ap if (needs_close) close( fd );
if (!NT_ERROR(status)) - file_complete_async( device, event, apc, apc_user, io, status, sz ); + file_complete_async( device, options, event, apc, apc_user, io, status, sz ); return status; }
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index b10d51f3c60..269197e41f2 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1460,6 +1460,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc UINT code, void *in_buffer, UINT in_size, void *out_buffer, UINT out_size ) { int fd, needs_close = FALSE; + unsigned int options; NTSTATUS status;
TRACE( "handle %p, code %#x, in_buffer %p, in_size %u, out_buffer %p, out_size %u\n", @@ -1525,6 +1526,10 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc break; }
+ if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, &options ))) + return status; + if (needs_close) close( fd ); + SERVER_START_REQ( socket_get_events ) { req->handle = wine_server_obj_handle( handle ); @@ -1535,7 +1540,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc } SERVER_END_REQ;
- file_complete_async( handle, event, apc, apc_user, io, status, 0 ); + file_complete_async( handle, options, event, apc, apc_user, io, status, 0 ); return status; }
@@ -1681,8 +1686,12 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc if (in_size != sizeof(NTSTATUS)) return STATUS_BUFFER_TOO_SMALL;
+ if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, &options ))) + return status; + if (needs_close) close( fd ); + status = *(NTSTATUS *)in_buffer; - file_complete_async( handle, event, apc, apc_user, io, status, 0 ); + file_complete_async( handle, options, event, apc, apc_user, io, status, 0 ); return status; }
@@ -1696,7 +1705,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc break; }
- if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) + if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, &options ))) return status;
#ifdef linux @@ -1708,7 +1717,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc { *(int *)out_buffer = 0; if (needs_close) close( fd ); - file_complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 ); + file_complete_async( handle, options, event, apc, apc_user, io, STATUS_SUCCESS, 0 ); return STATUS_SUCCESS; } } @@ -1721,7 +1730,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc } *(int *)out_buffer = value; if (needs_close) close( fd ); - file_complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 ); + file_complete_async( handle, options, event, apc, apc_user, io, STATUS_SUCCESS, 0 ); return STATUS_SUCCESS; }
@@ -1730,7 +1739,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc int value, ret; socklen_t len = sizeof(value);
- if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) + if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, &options ))) return status;
if (out_size < sizeof(int)) @@ -1760,7 +1769,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc *(int *)out_buffer = !value; } if (needs_close) close( fd ); - file_complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 ); + file_complete_async( handle, options, event, apc, apc_user, io, STATUS_SUCCESS, 0 ); return STATUS_SUCCESS; }
@@ -1772,6 +1781,10 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc unsigned int count = 0; ULONG ret_size;
+ if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, &options ))) + return status; + if (needs_close) close( fd ); + if (getifaddrs( &ifaddrs ) < 0) { status = sock_errno_to_status( errno ); @@ -1787,7 +1800,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc if (out_size < ret_size) { freeifaddrs( ifaddrs ); - file_complete_async( handle, event, apc, apc_user, io, STATUS_BUFFER_TOO_SMALL, 0 ); + file_complete_async( handle, options, event, apc, apc_user, io, STATUS_BUFFER_TOO_SMALL, 0 ); return STATUS_PENDING; }
@@ -1837,7 +1850,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc }
freeifaddrs( ifaddrs ); - file_complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, ret_size ); + file_complete_async( handle, options, event, apc, apc_user, io, STATUS_SUCCESS, ret_size ); return STATUS_PENDING; #else FIXME( "Interface list queries are currently not supported on this platform.\n" ); @@ -1855,7 +1868,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc return STATUS_BUFFER_TOO_SMALL; keepalive = !!k->onoff;
- if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) + if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, &options ))) return status;
if (setsockopt( fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(int) ) < 0) @@ -1892,7 +1905,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc }
if (needs_close) close( fd ); - file_complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, 0 ); + file_complete_async( handle, options, event, apc, apc_user, io, STATUS_SUCCESS, 0 ); return STATUS_SUCCESS; }
diff --git a/dlls/ntdll/unix/tape.c b/dlls/ntdll/unix/tape.c index 366096bbf4f..366e12c35a0 100644 --- a/dlls/ntdll/unix/tape.c +++ b/dlls/ntdll/unix/tape.c @@ -523,12 +523,13 @@ NTSTATUS tape_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE apc, { DWORD sz = 0; NTSTATUS status = STATUS_INVALID_PARAMETER; + unsigned int options; int fd, needs_close;
TRACE( "%p %s %p %d %p %d %p\n", device, io2str(code), in_buffer, in_size, out_buffer, out_size, io );
- if ((status = server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL ))) + if ((status = server_get_unix_fd( device, 0, &fd, &needs_close, NULL, &options ))) return status;
switch (code) @@ -580,6 +581,6 @@ NTSTATUS tape_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE apc, if (needs_close) close( fd );
if (!NT_ERROR(status)) - file_complete_async( device, event, apc, apc_user, io, status, sz ); + file_complete_async( device, options, event, apc, apc_user, io, status, sz ); return status; } diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 2e0477e42e0..41c7ab4ff2c 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -354,7 +354,7 @@ extern NTSTATUS open_unix_file( HANDLE *handle, const char *unix_name, ACCESS_MA extern NTSTATUS get_device_info( int fd, struct _FILE_FS_DEVICE_INFORMATION *info ); extern void init_files(void); extern void init_cpu_info(void); -extern void file_complete_async( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, +extern void file_complete_async( HANDLE handle, unsigned int options, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, IO_STATUS_BLOCK *io, NTSTATUS status, ULONG_PTR information ); extern void set_async_direct_result( HANDLE *async_handle, IO_STATUS_BLOCK *io, NTSTATUS status, ULONG_PTR information, BOOL mark_pending );
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ntdll/unix/file.c | 7 ++----- dlls/ntdll/unix/serial.c | 4 ++-- dlls/ntdll/unix/socket.c | 6 +++--- dlls/ntdll/unix/unix_private.h | 2 +- 4 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 2ab04040258..cb3fa75597f 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -5484,7 +5484,7 @@ static void add_completion( HANDLE handle, ULONG_PTR value, NTSTATUS status, ULO }
/* notify direct completion of async and close the wait handle if it is no longer needed */ -void set_async_direct_result( HANDLE *async_handle, IO_STATUS_BLOCK *io, +void set_async_direct_result( HANDLE *async_handle, unsigned int options, IO_STATUS_BLOCK *io, NTSTATUS status, ULONG_PTR information, BOOL mark_pending ) { unsigned int ret; @@ -5493,10 +5493,7 @@ void set_async_direct_result( HANDLE *async_handle, IO_STATUS_BLOCK *io, assert( *async_handle );
if (!NT_ERROR(status) && status != STATUS_PENDING) - { - io->Status = status; - io->Information = information; - } + set_sync_iosb( io, status, information, options );
SERVER_START_REQ( set_async_direct_result ) { diff --git a/dlls/ntdll/unix/serial.c b/dlls/ntdll/unix/serial.c index 89b12980df7..c47adaf2054 100644 --- a/dlls/ntdll/unix/serial.c +++ b/dlls/ntdll/unix/serial.c @@ -1203,12 +1203,12 @@ static NTSTATUS wait_on( HANDLE handle, int fd, HANDLE event, PIO_APC_ROUTINE ap { status = STATUS_SUCCESS; *out_buffer = events; - set_async_direct_result( &wait_handle, io, STATUS_SUCCESS, sizeof(events), FALSE ); + set_async_direct_result( &wait_handle, options, io, STATUS_SUCCESS, sizeof(events), FALSE ); } else { status = STATUS_PENDING; - set_async_direct_result( &wait_handle, io, STATUS_PENDING, 0, TRUE ); + set_async_direct_result( &wait_handle, options, io, STATUS_PENDING, 0, TRUE ); } }
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 269197e41f2..a2b7b9fd051 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -875,7 +875,7 @@ static NTSTATUS sock_recv( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi status = try_recv( fd, async, &information ); if (status == STATUS_DEVICE_NOT_READY && (force_async || !nonblocking)) status = STATUS_PENDING; - set_async_direct_result( &wait_handle, io, status, information, FALSE ); + set_async_direct_result( &wait_handle, options, io, status, information, FALSE ); }
if (status != STATUS_PENDING) @@ -1131,7 +1131,7 @@ static NTSTATUS sock_send( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi if (status == STATUS_DEVICE_NOT_READY && async->sent_len) status = STATUS_SUCCESS;
- set_async_direct_result( &wait_handle, io, status, async->sent_len, FALSE ); + set_async_direct_result( &wait_handle, options, io, status, async->sent_len, FALSE ); }
if (status != STATUS_PENDING) @@ -1387,7 +1387,7 @@ static NTSTATUS sock_transmit( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, status = STATUS_PENDING;
information = async->head_cursor + async->file_cursor + async->tail_cursor; - set_async_direct_result( &wait_handle, io, status, information, TRUE ); + set_async_direct_result( &wait_handle, options, io, status, information, TRUE ); }
if (status != STATUS_PENDING) diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 41c7ab4ff2c..6cd88a5acc0 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -356,7 +356,7 @@ extern void init_files(void); extern void init_cpu_info(void); extern void file_complete_async( HANDLE handle, unsigned int options, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, IO_STATUS_BLOCK *io, NTSTATUS status, ULONG_PTR information ); -extern void set_async_direct_result( HANDLE *async_handle, IO_STATUS_BLOCK *io, +extern void set_async_direct_result( HANDLE *async_handle, unsigned int options, IO_STATUS_BLOCK *io, NTSTATUS status, ULONG_PTR information, BOOL mark_pending );
extern NTSTATUS unixcall_wine_dbg_write( void *args );
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ntdll/unix/file.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index cb3fa75597f..15fdf2cb021 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -5721,8 +5721,7 @@ err: if (needs_close) close( unix_handle ); if (status == STATUS_SUCCESS || (status == STATUS_END_OF_FILE && (!async_read || type == FD_TYPE_FILE))) { - io->Status = status; - io->Information = total; + set_sync_iosb( io, status, total, options ); TRACE("= SUCCESS (%u)\n", total); if (event) NtSetEvent( event, NULL ); if (apc && (!status || async_read)) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc, @@ -5802,8 +5801,7 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap send_completion = cvalue != 0;
if (needs_close) close( unix_handle ); - io->Status = status; - io->Information = total; + set_sync_iosb( io, status, total, options ); TRACE("= 0x%08x (%u)\n", status, total); if (event) NtSetEvent( event, NULL ); if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc, (ULONG_PTR)apc_user, iosb_ptr, 0 ); @@ -6031,8 +6029,7 @@ err:
if (status == STATUS_SUCCESS) { - io->Status = status; - io->Information = total; + set_sync_iosb( io, status, total, options ); TRACE("= SUCCESS (%u)\n", total); if (event) NtSetEvent( event, NULL ); if (apc) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc, (ULONG_PTR)apc_user, iosb_ptr, 0 );
On Wed Jun 26 12:23:22 2024 +0000, Alexandre Julliard wrote:
`options` is never initialized here.
Oops, fixed in v2.