[PATCH v3 4/5] ntdll: Return STATUS_PENDING from NtWriteFile() for async write.

Jacek Caban jacek at codeweavers.com
Tue Feb 26 08:23:04 CST 2019


Hi Paul,

On 2/20/19 7:50 PM, Paul Gofman wrote:
> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42982
>
> This matches Vista+ behaviour.
>
> Signed-off-by: Paul Gofman <gofmanp at gmail.com>
> ---
> v2, v3: no changes.
>
>   dlls/ntdll/file.c       | 7 ++++---
>   dlls/ntdll/tests/file.c | 6 +++---
>   2 files changed, 7 insertions(+), 6 deletions(-)
>
> diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
> index ffedbeb534..b6307a2436 100644
> --- a/dlls/ntdll/file.c
> +++ b/dlls/ntdll/file.c
> @@ -1199,7 +1199,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
>       int result, unix_handle, needs_close;
>       unsigned int options;
>       struct io_timeouts timeouts;
> -    NTSTATUS status;
> +    NTSTATUS status, ret_status;
>       ULONG total = 0;
>       enum server_fd_type type;
>       ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_user;
> @@ -1409,9 +1409,10 @@ err:
>           if (status != STATUS_PENDING && hEvent) NtResetEvent( hEvent, NULL );
>       }
>   
> -    if (send_completion) NTDLL_AddCompletion( hFile, cvalue, status, total, FALSE );
> +    ret_status = async_write && status == STATUS_SUCCESS ? STATUS_PENDING : status;
> +    if (send_completion) NTDLL_AddCompletion( hFile, cvalue, status, total, ret_status == STATUS_PENDING );
>   
> -    return status;
> +    return ret_status;


While it generally looks like Vista+ indeed returns STATUS_PENDING in 
quite a lot of situations, doing it always in all cases is probably not 
the right thing. For example, read()/write() on overlapped named pipes 
does not return STATUS_PENDING if the request may be completed 
immediately. Although named pipe read/write use different code path in 
Wine, the general concern remains: we can't assume that Windows does 
that unconditionally for all all overlapped requests.


That said, I think it needs more investigation. I know that our tests 
may not be great to check that as they accept both pre-Vista and Vista+ 
behaviour as valid, but maybe marking pre-Vista results as broken() 
would be a good start so that we can see an evidence that it's a correct 
thing to do (depending on outcome, those broken()s are may or may not be 
something we want in Wine, but it would surely be useful for 
investigation). Some experimentation with different object types could 
give us useful info as well.


Also note that such change may need throughout review of Wine to make 
sure that we don't depend on pre-Vista behaviour in our code. 
read()/write() should be safer, but I've seen STATUS_PENDING returned 
from ioctl()s as well (even on pipes), and changing that would surely 
break kernel32 code.


Thanks,

Jacek




More information about the wine-devel mailing list