Signed-off-by: Brendan Shanks bshanks@codeweavers.com --- v3: Test 1 byte overlapped reads with different sizes of nonblocking writes
dlls/kernel32/tests/pipe.c | 165 +++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c index f61d441303..dbc4642b82 100644 --- a/dlls/kernel32/tests/pipe.c +++ b/dlls/kernel32/tests/pipe.c @@ -3887,6 +3887,170 @@ static void test_wait_pipe(void) CloseHandle(ov.hEvent); }
+static void test_nowait(void) +{ + HANDLE piperead, pipewrite, hFile; + OVERLAPPED ol, ol2; + DWORD read, write; + char readbuf[32768]; + static const char teststring[] = "bits"; + + /* CreateNamedPipe with PIPE_NOWAIT, and read from empty pipe */ + piperead = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, + /* dwPipeMode */ PIPE_TYPE_BYTE | PIPE_NOWAIT, + /* nMaxInstances */ 1, + /* nOutBufSize */ 512, + /* nInBufSize */ 512, + /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT, + /* lpSecurityAttrib */ NULL); + ok(piperead != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n"); + pipewrite = CreateFileA(PIPENAME, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); + ok(pipewrite != INVALID_HANDLE_VALUE, "CreateFileA failed\n"); + memset(&ol, 0, sizeof(ol)); + ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + SetLastError(0xdeadbeef); + ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol) == FALSE, "ReadFile should fail\n"); + todo_wine ok(GetLastError() == ERROR_NO_DATA, "got %d should be ERROR_NO_DATA\n", GetLastError()); + if (GetLastError() == ERROR_IO_PENDING) + CancelIo(piperead); + + /* test a small write/read */ + ok(WriteFile(pipewrite, teststring, sizeof(teststring), &write, NULL), "WriteFile should succeed\n"); + ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol), "ReadFile should succeed\n"); + ok(read == write, "read/write bytes should match\n"); + ok(CloseHandle(ol.hEvent), "CloseHandle for the event failed\n"); + ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n"); + ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n"); + + + /* create write side with PIPE_NOWAIT, read side PIPE_WAIT, and test writes */ + pipewrite = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, + /* dwPipeMode */ PIPE_TYPE_BYTE | PIPE_NOWAIT, + /* nMaxInstances */ 1, + /* nOutBufSize */ 512, + /* nInBufSize */ 512, + /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT, + /* lpSecurityAttrib */ NULL); + ok(pipewrite != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n"); + piperead = CreateFileA(PIPENAME, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + ok(piperead != INVALID_HANDLE_VALUE, "CreateFileA failed\n"); + memset(&ol, 0, sizeof(ol)); + ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + memset(&ol2, 0, sizeof(ol2)); + ol2.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + + /* write one byte larger than the buffer size, should fail */ + SetLastError(0xdeadbeef); + todo_wine ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n"); + /* WriteFile only documents that 'write < sizeof(readbuf)' for this case, but Windows + * doesn't seem to do partial writes ('write == 0' always) + */ + ok(write < sizeof(readbuf), "WriteFile should fail to write the whole buffer\n"); + ok(write == 0, "WriteFile doesn't do partial writes here\n"); + if (GetLastError() == ERROR_IO_PENDING) + CancelIo(piperead); + + /* overlapped read of 32768, non-blocking write of 512 */ + SetLastError(0xdeadbeef); + todo_wine ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2) == FALSE, "ReadFile should fail\n"); + todo_wine ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError()); + ok(WriteFile(pipewrite, teststring, sizeof(teststring), &write, &ol), "WriteFile should succeed\n"); + ok(write == sizeof(teststring), "got %d, write should be %d\n", write, sizeof(teststring)); + ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n"); + todo_wine ok(read == sizeof(teststring), "got %d, read should be %d\n", read, sizeof(teststring)); + if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE) + CancelIo(piperead); + + /* overlapped read of 32768, non-blocking write of 513 */ + SetLastError(0xdeadbeef); + todo_wine ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2) == FALSE, "ReadFile should fail\n"); + todo_wine ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError()); + todo_wine ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n"); + todo_wine ok(write == 513, "got %d, write should be %d\n", write, 513); + ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n"); + todo_wine ok(read == 513, "got %d, read should be %d\n", read, 513); + if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE) + CancelIo(piperead); + + /* overlapped read of 1 byte, non-blocking write of 513 bytes */ + SetLastError(0xdeadbeef); + todo_wine ok(ReadFile(piperead, readbuf, 1, &read, &ol2) == FALSE, "ReadFile should fail\n"); + todo_wine ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError()); + todo_wine ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n"); + todo_wine ok(write == 513, "got %d, write should be %d\n", write, 513); + ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n"); + ok(read == 1, "got %d, read should be %d\n", read, 1); + if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE) + CancelIo(piperead); + /* read the remaining 512 bytes */ + SetLastError(0xdeadbeef); + ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2), "ReadFile should succeed\n"); + todo_wine ok(read == 512, "got %d, write should be %d\n", write, 512); + if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE) + CancelIo(piperead); + + /* overlapped read of 1 byte, non-blocking write of 514 bytes */ + SetLastError(0xdeadbeef); + ok(ReadFile(piperead, readbuf, 1, &read, &ol2) == FALSE, "ReadFile should fail\n"); + ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError()); + todo_wine ok(WriteFile(pipewrite, readbuf, 514, &write, &ol), "WriteFile should succeed\n"); + todo_wine ok(write == 1, "got %d, write should be %d\n", write, 1); + ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n"); + ok(read == 1, "got %d, read should be %d\n", read, 1); + if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE) + CancelIo(piperead); + + /* write the exact buffer size, should succeed */ + SetLastError(0xdeadbeef); + todo_wine ok(WriteFile(pipewrite, readbuf, 512, &write, &ol), "WriteFile should succeed\n"); + todo_wine ok(write == 512, "WriteFile should write the whole buffer\n"); + if (GetLastError() == ERROR_IO_PENDING) + CancelIo(piperead); + + ok(CloseHandle(ol.hEvent), "CloseHandle for the event failed\n"); + ok(CloseHandle(ol2.hEvent), "CloseHandle for the event failed\n"); + ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n"); + ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n"); + + + /* CreateNamedPipe with PIPE_NOWAIT, test ConnectNamedPipe */ + pipewrite = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, + /* dwPipeMode */ PIPE_TYPE_BYTE | PIPE_NOWAIT, + /* nMaxInstances */ 1, + /* nOutBufSize */ 512, + /* nInBufSize */ 512, + /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT, + /* lpSecurityAttrib */ NULL); + ok(pipewrite != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n"); + memset(&ol, 0, sizeof(ol)); + ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + SetLastError(0xdeadbeef); + ok(ConnectNamedPipe(pipewrite, &ol) == FALSE, "ConnectNamedPipe should fail\n"); + todo_wine ok(GetLastError() == ERROR_PIPE_LISTENING, "got %d should be ERROR_PIPE_LISTENING\n", GetLastError()); + if (GetLastError() == ERROR_IO_PENDING) + CancelIo(pipewrite); + + /* connect and disconnect, then test ConnectNamedPipe again */ + hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); + ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA failed\n"); + ok(CloseHandle(hFile), "CloseHandle failed\n"); + SetLastError(0xdeadbeef); + ok(ConnectNamedPipe(pipewrite,&ol) == FALSE, "ConnectNamedPipe should fail\n"); + ok(GetLastError() == ERROR_NO_DATA, "got %d should be ERROR_NO_DATA\n", GetLastError()); + if (GetLastError() == ERROR_IO_PENDING) + CancelIo(pipewrite); + + /* call DisconnectNamedPipe and test ConnectNamedPipe again */ + ok(DisconnectNamedPipe(pipewrite) == TRUE, "DisconnectNamedPipe should succeed\n"); + SetLastError(0xdeadbeef); + ok(ConnectNamedPipe(pipewrite,&ol) == FALSE, "ConnectNamedPipe should fail\n"); + todo_wine ok(GetLastError() == ERROR_PIPE_LISTENING, "got %d should be ERROR_PIPE_LISTENING\n", GetLastError()); + if (GetLastError() == ERROR_IO_PENDING) + CancelIo(pipewrite); + ok(CloseHandle(ol.hEvent), "CloseHandle for the event failed\n"); + ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n"); +} + START_TEST(pipe) { char **argv; @@ -3954,4 +4118,5 @@ START_TEST(pipe) test_namedpipe_session_id(); test_multiple_instances(); test_wait_pipe(); + test_nowait(); }
Fixes Rockstar Games Launcher hanging for some users.
Signed-off-by: Brendan Shanks bshanks@codeweavers.com --- dlls/kernel32/tests/pipe.c | 2 +- server/named_pipe.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c index dbc4642b82..59f1684c2a 100644 --- a/dlls/kernel32/tests/pipe.c +++ b/dlls/kernel32/tests/pipe.c @@ -3910,7 +3910,7 @@ static void test_nowait(void) ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); SetLastError(0xdeadbeef); ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol) == FALSE, "ReadFile should fail\n"); - todo_wine ok(GetLastError() == ERROR_NO_DATA, "got %d should be ERROR_NO_DATA\n", GetLastError()); + ok(GetLastError() == ERROR_NO_DATA, "got %d should be ERROR_NO_DATA\n", GetLastError()); if (GetLastError() == ERROR_IO_PENDING) CancelIo(piperead);
diff --git a/server/named_pipe.c b/server/named_pipe.c index 8e0380d060..6926712b8c 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -851,6 +851,11 @@ static int pipe_end_read( struct fd *fd, struct async *async, file_pos_t pos ) switch (pipe_end->state) { case FILE_PIPE_CONNECTED_STATE: + if ((pipe_end->flags & NAMED_PIPE_NONBLOCKING_MODE) && list_empty( &pipe_end->message_queue )) + { + set_error( STATUS_PIPE_EMPTY ); + return 0; + } break; case FILE_PIPE_DISCONNECTED_STATE: set_error( STATUS_PIPE_DISCONNECTED );
Signed-off-by: Brendan Shanks bshanks@codeweavers.com --- v3: Fix WriteFile result when nonblocking write completes partially
dlls/kernel32/tests/pipe.c | 36 ++++++++++++++++++------------------ server/named_pipe.c | 18 +++++++++++++----- 2 files changed, 31 insertions(+), 23 deletions(-)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c index 59f1684c2a..46b9e1c667 100644 --- a/dlls/kernel32/tests/pipe.c +++ b/dlls/kernel32/tests/pipe.c @@ -3941,7 +3941,7 @@ static void test_nowait(void)
/* write one byte larger than the buffer size, should fail */ SetLastError(0xdeadbeef); - todo_wine ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n"); + ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n"); /* WriteFile only documents that 'write < sizeof(readbuf)' for this case, but Windows * doesn't seem to do partial writes ('write == 0' always) */ @@ -3952,32 +3952,32 @@ static void test_nowait(void)
/* overlapped read of 32768, non-blocking write of 512 */ SetLastError(0xdeadbeef); - todo_wine ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2) == FALSE, "ReadFile should fail\n"); - todo_wine ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError()); + ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2) == FALSE, "ReadFile should fail\n"); + ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError()); ok(WriteFile(pipewrite, teststring, sizeof(teststring), &write, &ol), "WriteFile should succeed\n"); ok(write == sizeof(teststring), "got %d, write should be %d\n", write, sizeof(teststring)); ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n"); - todo_wine ok(read == sizeof(teststring), "got %d, read should be %d\n", read, sizeof(teststring)); + ok(read == sizeof(teststring), "got %d, read should be %d\n", read, sizeof(teststring)); if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE) CancelIo(piperead);
/* overlapped read of 32768, non-blocking write of 513 */ SetLastError(0xdeadbeef); - todo_wine ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2) == FALSE, "ReadFile should fail\n"); - todo_wine ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError()); - todo_wine ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n"); - todo_wine ok(write == 513, "got %d, write should be %d\n", write, 513); + ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2) == FALSE, "ReadFile should fail\n"); + ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError()); + ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n"); + ok(write == 513, "got %d, write should be %d\n", write, 513); ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n"); - todo_wine ok(read == 513, "got %d, read should be %d\n", read, 513); + ok(read == 513, "got %d, read should be %d\n", read, 513); if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE) CancelIo(piperead);
/* overlapped read of 1 byte, non-blocking write of 513 bytes */ SetLastError(0xdeadbeef); - todo_wine ok(ReadFile(piperead, readbuf, 1, &read, &ol2) == FALSE, "ReadFile should fail\n"); - todo_wine ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError()); - todo_wine ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n"); - todo_wine ok(write == 513, "got %d, write should be %d\n", write, 513); + ok(ReadFile(piperead, readbuf, 1, &read, &ol2) == FALSE, "ReadFile should fail\n"); + ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError()); + ok(WriteFile(pipewrite, readbuf, 513, &write, &ol), "WriteFile should succeed\n"); + ok(write == 513, "got %d, write should be %d\n", write, 513); ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n"); ok(read == 1, "got %d, read should be %d\n", read, 1); if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE) @@ -3985,7 +3985,7 @@ static void test_nowait(void) /* read the remaining 512 bytes */ SetLastError(0xdeadbeef); ok(ReadFile(piperead, readbuf, sizeof(readbuf), &read, &ol2), "ReadFile should succeed\n"); - todo_wine ok(read == 512, "got %d, write should be %d\n", write, 512); + ok(read == 512, "got %d, write should be %d\n", write, 512); if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE) CancelIo(piperead);
@@ -3993,8 +3993,8 @@ static void test_nowait(void) SetLastError(0xdeadbeef); ok(ReadFile(piperead, readbuf, 1, &read, &ol2) == FALSE, "ReadFile should fail\n"); ok(GetLastError() == ERROR_IO_PENDING, "got %d should be ERROR_IO_PENDING\n", GetLastError()); - todo_wine ok(WriteFile(pipewrite, readbuf, 514, &write, &ol), "WriteFile should succeed\n"); - todo_wine ok(write == 1, "got %d, write should be %d\n", write, 1); + ok(WriteFile(pipewrite, readbuf, 514, &write, &ol), "WriteFile should succeed\n"); + ok(write == 1, "got %d, write should be %d\n", write, 1); ok(GetOverlappedResult(piperead, &ol2, &read, FALSE), "GetOverlappedResult should succeed\n"); ok(read == 1, "got %d, read should be %d\n", read, 1); if (GetOverlappedResult(piperead, &ol2, &read, FALSE) == FALSE) @@ -4002,8 +4002,8 @@ static void test_nowait(void)
/* write the exact buffer size, should succeed */ SetLastError(0xdeadbeef); - todo_wine ok(WriteFile(pipewrite, readbuf, 512, &write, &ol), "WriteFile should succeed\n"); - todo_wine ok(write == 512, "WriteFile should write the whole buffer\n"); + ok(WriteFile(pipewrite, readbuf, 512, &write, &ol), "WriteFile should succeed\n"); + ok(write == 512, "WriteFile should write the whole buffer\n"); if (GetLastError() == ERROR_IO_PENDING) CancelIo(piperead);
diff --git a/server/named_pipe.c b/server/named_pipe.c index 6926712b8c..3db8f778a5 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -363,7 +363,7 @@ static struct pipe_message *queue_message( struct pipe_end *pipe_end, struct ios return message; }
-static void wake_message( struct pipe_message *message ) +static void wake_message( struct pipe_message *message, data_size_t result ) { struct async *async = message->async;
@@ -371,7 +371,7 @@ static void wake_message( struct pipe_message *message ) if (!async) return;
message->iosb->status = STATUS_SUCCESS; - message->iosb->result = message->iosb->in_size; + message->iosb->result = result; async_terminate( async, message->iosb->result ? STATUS_ALERTED : STATUS_SUCCESS ); release_object( async ); } @@ -749,7 +749,7 @@ static void message_queue_read( struct pipe_end *pipe_end, struct iosb *iosb ) { iosb->out_data = message->iosb->in_data; message->iosb->in_data = NULL; - wake_message( message ); + wake_message( message, message->iosb->in_size ); free_message( message ); } else @@ -773,7 +773,7 @@ static void message_queue_read( struct pipe_end *pipe_end, struct iosb *iosb ) message->read_pos += writing; if (message->read_pos == message->iosb->in_size) { - wake_message(message); + wake_message(message, message->iosb->in_size); free_message(message); } } while (write_pos < iosb->out_size); @@ -836,7 +836,15 @@ static void reselect_write_queue( struct pipe_end *pipe_end ) { avail += message->iosb->in_size - message->read_pos; if (message->async && (avail <= reader->buffer_size || !message->iosb->in_size)) - wake_message( message ); + { + wake_message( message, message->iosb->in_size ); + } + else if (message->async && (pipe_end->flags & NAMED_PIPE_NONBLOCKING_MODE) && + !async_waiting( &reader->read_q )) + { + wake_message( message, message->read_pos ); + free_message( message ); + } } }
Hi Brendan,
On 10/3/19 9:57 PM, Brendan Shanks wrote:
else if (message->async && (pipe_end->flags & NAMED_PIPE_NONBLOCKING_MODE) &&
!async_waiting( &reader->read_q ))
async_waiting() may not do the right thing here. Note that it checks only head of the queue. We may have the head complete (for example cancelled, but the result is still being passed to the client). You may check find_pending_async() result instead.
Jacek
On Oct 4, 2019, at 9:17 AM, Jacek Caban jacek@codeweavers.com wrote:
Hi Brendan,
On 10/3/19 9:57 PM, Brendan Shanks wrote:
else if (message->async && (pipe_end->flags & NAMED_PIPE_NONBLOCKING_MODE) &&
!async_waiting( &reader->read_q ))
async_waiting() may not do the right thing here. Note that it checks only head of the queue. We may have the head complete (for example cancelled, but the result is still being passed to the client). You may check find_pending_async() result instead.
Thanks, that makes sense. I made the change and will send another version out.
Brendan
Signed-off-by: Brendan Shanks bshanks@codeweavers.com --- dlls/kernel32/tests/pipe.c | 4 ++-- server/named_pipe.c | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c index 46b9e1c667..f53a59db14 100644 --- a/dlls/kernel32/tests/pipe.c +++ b/dlls/kernel32/tests/pipe.c @@ -4026,7 +4026,7 @@ static void test_nowait(void) ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); SetLastError(0xdeadbeef); ok(ConnectNamedPipe(pipewrite, &ol) == FALSE, "ConnectNamedPipe should fail\n"); - todo_wine ok(GetLastError() == ERROR_PIPE_LISTENING, "got %d should be ERROR_PIPE_LISTENING\n", GetLastError()); + ok(GetLastError() == ERROR_PIPE_LISTENING, "got %d should be ERROR_PIPE_LISTENING\n", GetLastError()); if (GetLastError() == ERROR_IO_PENDING) CancelIo(pipewrite);
@@ -4044,7 +4044,7 @@ static void test_nowait(void) ok(DisconnectNamedPipe(pipewrite) == TRUE, "DisconnectNamedPipe should succeed\n"); SetLastError(0xdeadbeef); ok(ConnectNamedPipe(pipewrite,&ol) == FALSE, "ConnectNamedPipe should fail\n"); - todo_wine ok(GetLastError() == ERROR_PIPE_LISTENING, "got %d should be ERROR_PIPE_LISTENING\n", GetLastError()); + ok(GetLastError() == ERROR_PIPE_LISTENING, "got %d should be ERROR_PIPE_LISTENING\n", GetLastError()); if (GetLastError() == ERROR_IO_PENDING) CancelIo(pipewrite); ok(CloseHandle(ol.hEvent), "CloseHandle for the event failed\n"); diff --git a/server/named_pipe.c b/server/named_pipe.c index 3db8f778a5..7dfd586a30 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -1108,6 +1108,12 @@ static int pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *as return 0; }
+ if (server->pipe_end.flags & NAMED_PIPE_NONBLOCKING_MODE) + { + set_error( STATUS_PIPE_LISTENING ); + return 0; + } + queue_async( &server->listen_q, async ); async_wake_up( &server->pipe_end.pipe->waiters, STATUS_SUCCESS ); set_error( STATUS_PENDING );