The client can set mark_pending to indicate that the full-blown I/O completion mechanism shall be triggered (asynchronous completion) even if the status indicates failure.
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/ntdll/unix/socket.c | 2 +- dlls/ntdll/unix/sync.c | 9 +++++---- dlls/ntdll/unix/unix_private.h | 2 +- server/async.c | 11 ++++++++--- server/protocol.def | 1 + 5 files changed, 16 insertions(+), 9 deletions(-)
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 75f03706401..b0458849adb 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/server/async.c b/server/async.c index a5afa4ebd39..39e65d65ad3 100644 --- a/server/async.c +++ b/server/async.c @@ -801,10 +801,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 5b8a49f8aca..cec2c644957 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2168,6 +2168,7 @@ enum message_type obj_handle_t handle; /* wait handle */ unsigned int status; /* completion status */ apc_param_t information; /* IO_STATUS_BLOCK Information */ + int mark_pending; /* set async to pending before completion? */ @REPLY obj_handle_t handle; /* wait handle, or NULL if closed */ @END