diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 23059e3cff8..2f8bd6e62bf 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -767,7 +767,7 @@ static NTSTATUS sock_recv( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi release_fileio( &async->io ); } - if (alerted) set_async_direct_result( &wait_handle, status, information ); + if (alerted) set_async_direct_result( &wait_handle, status, information, FALSE ); if (wait_handle) status = wait_async( wait_handle, options & FILE_SYNCHRONOUS_IO_ALERT ); return status; } diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index ee25dfd0099..0786454dad2 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -2514,7 +2514,7 @@ NTSTATUS WINAPI NtWaitForAlertByThreadId( const void *address, const LARGE_INTEG /* Notify direct completion of async and close the wait handle if it is no longer needed. * This function is a no-op (returns status as-is) if the supplied handle is NULL. */ -void set_async_direct_result( HANDLE *optional_handle, NTSTATUS status, ULONG_PTR information ) +void set_async_direct_result( HANDLE *optional_handle, NTSTATUS status, ULONG_PTR information, BOOL mark_pending ) { NTSTATUS ret; @@ -2522,9 +2522,10 @@ void set_async_direct_result( HANDLE *optional_handle, NTSTATUS status, ULONG_PT SERVER_START_REQ( set_async_direct_result ) { - req->handle = wine_server_obj_handle( *optional_handle ); - req->status = status; - req->information = information; + req->handle = wine_server_obj_handle( *optional_handle ); + req->status = status; + req->information = information; + req->mark_pending = mark_pending; ret = wine_server_call( req ); if (ret == STATUS_SUCCESS) *optional_handle = wine_server_ptr_handle( reply->handle ); diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 434f98cdc5a..86e87e6e29a 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -274,7 +274,7 @@ extern NTSTATUS get_device_info( int fd, struct _FILE_FS_DEVICE_INFORMATION *inf extern void init_files(void) DECLSPEC_HIDDEN; extern void init_cpu_info(void) DECLSPEC_HIDDEN; extern void add_completion( HANDLE handle, ULONG_PTR value, NTSTATUS status, ULONG info, BOOL async ) DECLSPEC_HIDDEN; -extern void set_async_direct_result( HANDLE *optional_handle, NTSTATUS status, ULONG_PTR information ); +extern void set_async_direct_result( HANDLE *optional_handle, NTSTATUS status, ULONG_PTR information, BOOL mark_pending ); extern void dbg_init(void) DECLSPEC_HIDDEN; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index e32ef8e1479..75b48d7601c 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2913,7 +2913,7 @@ struct set_async_direct_result_request obj_handle_t handle; apc_param_t information; unsigned int status; - char __pad_28[4]; + int mark_pending; }; struct set_async_direct_result_reply { @@ -6284,7 +6284,7 @@ union generic_reply /* ### protocol_version begin ### */ -#define SERVER_PROTOCOL_VERSION 746 +#define SERVER_PROTOCOL_VERSION 747 /* ### protocol_version end ### */ diff --git a/server/async.c b/server/async.c index d49fb8b7c04..a92798fcd39 100644 --- a/server/async.c +++ b/server/async.c @@ -772,10 +772,15 @@ DECL_HANDLER(set_async_direct_result) async->direct_result = 0; async->pending = 1; } + else if (req->mark_pending) + { + async->pending = 1; + } - /* if the I/O has completed successfully, the client would have already - * set the IOSB. therefore, we can skip waiting on wait_handle and do - * async_set_result() directly. + /* if the I/O has completed successfully (or unsuccessfully, and + * async->pending is set), the client would have already set the IOSB. + * therefore, we can do async_set_result() directly and let the client skip + * waiting on wait_handle. */ async_set_result( &async->obj, status, req->information ); diff --git a/server/protocol.def b/server/protocol.def index 9d90544fa41..66c6c97b1e0 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2168,6 +2168,7 @@ enum message_type obj_handle_t handle; /* wait handle */ apc_param_t information; /* IO_STATUS_BLOCK Information */ unsigned int status; /* completion status */ + int mark_pending; /* set async to pending before completion? */ @REPLY obj_handle_t handle; /* wait handle, or NULL if closed */ @END diff --git a/server/request.h b/server/request.h index 2c7889bd197..434041490c0 100644 --- a/server/request.h +++ b/server/request.h @@ -1401,6 +1401,7 @@ C_ASSERT( sizeof(struct get_async_result_reply) == 8 ); C_ASSERT( FIELD_OFFSET(struct set_async_direct_result_request, handle) == 12 ); C_ASSERT( FIELD_OFFSET(struct set_async_direct_result_request, information) == 16 ); C_ASSERT( FIELD_OFFSET(struct set_async_direct_result_request, status) == 24 ); +C_ASSERT( FIELD_OFFSET(struct set_async_direct_result_request, mark_pending) == 28 ); C_ASSERT( sizeof(struct set_async_direct_result_request) == 32 ); C_ASSERT( FIELD_OFFSET(struct set_async_direct_result_reply, handle) == 8 ); C_ASSERT( sizeof(struct set_async_direct_result_reply) == 16 ); diff --git a/server/trace.c b/server/trace.c index 61e592b0ffa..75bc35b6b56 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2763,6 +2763,7 @@ static void dump_set_async_direct_result_request( const struct set_async_direct_ fprintf( stderr, " handle=%04x", req->handle ); dump_uint64( ", information=", &req->information ); fprintf( stderr, ", status=%08x", req->status ); + fprintf( stderr, ", mark_pending=%d", req->mark_pending ); } static void dump_set_async_direct_result_reply( const struct set_async_direct_result_reply *req )