This fixes various corner cases.
This is not motivated by any particular application. However, the server-side code seems at least as simple as the existing client-side code, is more accurate, and removes a potential source of complication from any future work involving asyncs.
From: Elizabeth Figura zfigura@codeweavers.com
Named pipes are now implemented entirely on the server side, and there is no code that warrants a separate FD type. --- server/named_pipe.c | 2 +- server/protocol.def | 1 - 2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/server/named_pipe.c b/server/named_pipe.c index f3404a33c3b..dd8c14b30a9 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -1016,7 +1016,7 @@ static void pipe_end_reselect_async( struct fd *fd, struct async_queue *queue )
static enum server_fd_type pipe_end_get_fd_type( struct fd *fd ) { - return FD_TYPE_PIPE; + return FD_TYPE_DEVICE; }
static void pipe_end_peek( struct pipe_end *pipe_end ) diff --git a/server/protocol.def b/server/protocol.def index 91257fce3a1..3c6596aebe2 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1500,7 +1500,6 @@ enum server_fd_type FD_TYPE_DIR, /* directory */ FD_TYPE_SOCKET, /* socket */ FD_TYPE_SERIAL, /* serial port */ - FD_TYPE_PIPE, /* named pipe */ FD_TYPE_MAILSLOT, /* mailslot */ FD_TYPE_CHAR, /* unspecified char device */ FD_TYPE_DEVICE, /* Windows device file */
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/kernel32/tests/mailslot.c | 106 ++++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/mailslot.c b/dlls/kernel32/tests/mailslot.c index a23aad96995..23f1a14df20 100644 --- a/dlls/kernel32/tests/mailslot.c +++ b/dlls/kernel32/tests/mailslot.c @@ -22,18 +22,24 @@ #include <stdlib.h> #include <stdio.h>
+#include <ntstatus.h> +#define WIN32_NO_STATUS #include <windef.h> #include <winbase.h> - +#include <winternl.h> #include "wine/test.h"
static const char szmspath[] = "\\.\mailslot\wine_mailslot_test";
static int mailslot_test(void) { + UNICODE_STRING nt_path = RTL_CONSTANT_STRING( L"\??\MAILSLOT\wine_mailslot_test" ); HANDLE hSlot, hSlot2, hWriter, hWriter2; unsigned char buffer[16]; DWORD count, dwMax, dwNext, dwMsgCount, dwTimeout; + FILE_MAILSLOT_QUERY_INFORMATION info; + OBJECT_ATTRIBUTES attr; + IO_STATUS_BLOCK io; BOOL ret;
/* sanity check on GetMailslotInfo */ @@ -102,6 +108,20 @@ static int mailslot_test(void) "slot write\n"); ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu\n", GetLastError() );
+ io.Status = 0xdeadbeef; + io.Information = 0xdeadbeef; + ret = NtReadFile( hSlot, NULL, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL ); + ok( ret == STATUS_IO_TIMEOUT, "got %#x\n", ret ); + ok( io.Status == 0xdeadbeef, "got status %#lx\n", io.Status ); + ok( io.Information == 0xdeadbeef, "got size %Iu\n", io.Information ); + + io.Status = 0xdeadbeef; + io.Information = 0xdeadbeef; + ret = NtWriteFile( hSlot, NULL, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL ); + ok( ret == STATUS_ACCESS_DENIED, "got %#x\n", ret ); + ok( io.Status == 0xdeadbeef, "got status %#lx\n", io.Status ); + ok( io.Information == 0xdeadbeef, "got size %Iu\n", io.Information ); + /* now try and open the client, but with the wrong sharing mode */ hWriter = CreateFileA(szmspath, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); @@ -141,6 +161,13 @@ static int mailslot_test(void) ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu\n", GetLastError() );
+ io.Status = 0xdeadbeef; + io.Information = 0xdeadbeef; + ret = NtReadFile( hWriter, NULL, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL ); + todo_wine ok( ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret ); + ok( io.Status == 0xdeadbeef, "got status %#lx\n", io.Status ); + ok( io.Information == 0xdeadbeef, "got size %Iu\n", io.Information ); + /* * seeing as there's something in the slot, * we should be able to read it once @@ -310,6 +337,48 @@ static int mailslot_test(void) if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %lu\n", GetLastError() ); else ok( count == 0, "wrong count %lu\n", count );
+ /* Try to perform a partial read. */ + count = 0; + ret = WriteFile( hWriter, buffer, 2, &count, NULL ); + ok( ret, "got %d\n", ret ); + ok( count == 2, "got count %lu\n", count ); + + io.Status = 0xdeadbeef; + io.Information = 0xdeadbeef; + ret = NtReadFile( hSlot, NULL, NULL, NULL, &io, buffer, 1, NULL, NULL ); + todo_wine ok( ret == STATUS_BUFFER_TOO_SMALL, "got %#x\n", ret ); + todo_wine ok( io.Status == 0xdeadbeef, "got status %#lx\n", io.Status ); + todo_wine ok( io.Information == 0xdeadbeef, "got size %Iu\n", io.Information ); + + io.Status = 0xdeadbeef; + io.Information = 0xdeadbeef; + memset( &info, 0xcc, sizeof(info) ); + ret = NtQueryInformationFile( hSlot, &io, &info, sizeof(info), FileMailslotQueryInformation ); + ok( ret == STATUS_SUCCESS, "got %#x\n", ret ); + ok( io.Status == STATUS_SUCCESS, "got status %#lx\n", io.Status ); + ok( io.Information == sizeof(info), "got size %Iu\n", io.Information ); + ok( !info.MaximumMessageSize, "got maximum size %lu\n", info.MaximumMessageSize ); + ok( !info.MailslotQuota, "got quota %lu\n", info.MailslotQuota ); + todo_wine ok( info.NextMessageSize == 2, "got next size %lu\n", info.NextMessageSize ); + todo_wine ok( info.MessagesAvailable == 1, "got message count %lu\n", info.MessagesAvailable ); + ok( !info.ReadTimeout.QuadPart, "got timeout %I64u\n", info.ReadTimeout.QuadPart ); + + io.Status = 0xdeadbeef; + io.Information = 0xdeadbeef; + memset( &info, 0xcc, sizeof(info) ); + ret = NtQueryInformationFile( hWriter, &io, &info, sizeof(info), FileMailslotQueryInformation ); + todo_wine + { + ok( ret == STATUS_SUCCESS, "got %#x\n", ret ); + ok( io.Status == STATUS_SUCCESS, "got status %#lx\n", io.Status ); + ok( io.Information == sizeof(info), "got size %Iu\n", io.Information ); + ok( !info.MaximumMessageSize, "got maximum size %lu\n", info.MaximumMessageSize ); + ok( !info.MailslotQuota, "got quota %lu\n", info.MailslotQuota ); + ok( info.NextMessageSize == 2, "got next size %lu\n", info.NextMessageSize ); + ok( info.MessagesAvailable == 1, "got message count %lu\n", info.MessagesAvailable ); + ok( !info.ReadTimeout.QuadPart, "got timeout %I64u\n", info.ReadTimeout.QuadPart ); + } + /* finally close the mailslot and its client */ ok( CloseHandle( hWriter2 ), "closing 2nd client\n"); ok( CloseHandle( hWriter ), "closing the client\n"); @@ -327,6 +396,41 @@ static int mailslot_test(void) ok( dwTimeout >= 900, "timeout too short %lu\n", dwTimeout ); ok( CloseHandle( hSlot ), "closing the mailslot\n");
+ InitializeObjectAttributes( &attr, &nt_path, 0, NULL, NULL ); + ret = NtCreateMailslotFile( &hSlot, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &attr, &io, 0, 0, 0, NULL ); + ok( !ret, "got %#x\n", ret ); + + io.Status = 0xdeadbeef; + io.Information = 0xdeadbeef; + ret = NtWriteFile( hSlot, NULL, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL ); + todo_wine ok( ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret ); + ok( io.Status == 0xdeadbeef, "got status %#lx\n", io.Status ); + ok( io.Information == 0xdeadbeef, "got size %Iu\n", io.Information ); + + io.Status = 0xdeadbeef; + io.Information = 0xdeadbeef; + ret = NtReadFile( hSlot, NULL, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL ); + todo_wine ok( ret == STATUS_PENDING, "got %#x\n", ret ); + ok( io.Status == 0xdeadbeef, "got status %#lx\n", io.Status ); + ok( io.Information == 0xdeadbeef, "got size %Iu\n", io.Information ); + + ret = WaitForSingleObject( hSlot, 0 ); + todo_wine ok( ret == WAIT_TIMEOUT, "got %d\n", ret ); + + hWriter = CreateFileA( szmspath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); + ok( hWriter != INVALID_HANDLE_VALUE, "got err %lu\n", GetLastError() ); + + ret = WriteFile( hWriter, "data", 4, &count, NULL ); + ok( ret == TRUE, "got error %lu\n", GetLastError() ); + + ret = WaitForSingleObject( hSlot, 1000 ); + ok( !ret, "got %d\n", ret ); + todo_wine ok( !io.Status, "got status %#lx\n", io.Status ); + todo_wine ok( io.Information == 4, "got size %Iu\n", io.Information ); + + CloseHandle( hWriter ); + CloseHandle( hSlot ); + return 0; }
From: Elizabeth Figura zfigura@codeweavers.com
That is, don't fill the IOSB or signal completion (unless the async was explicitly marked as pending, with set_async_pending().
This is for convenience. --- server/async.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/server/async.c b/server/async.c index 80129ac0ac3..3c9b9588c6e 100644 --- a/server/async.c +++ b/server/async.c @@ -368,16 +368,6 @@ obj_handle_t async_handoff( struct async *async, data_size_t *result, int force_
async->initial_status = get_error();
- if (!async->pending && NT_ERROR( get_error() )) - { - async->iosb->status = get_error(); - async_call_completion_callback( async ); - - close_handle( async->thread->process, async->wait_handle ); - async->wait_handle = 0; - return 0; - } - if (get_error() != STATUS_PENDING) { /* status and data are already set and returned */ @@ -393,6 +383,16 @@ obj_handle_t async_handoff( struct async *async, data_size_t *result, int force_ } }
+ if (!async->pending && NT_ERROR( async->iosb->status )) + { + async_call_completion_callback( async ); + + close_handle( async->thread->process, async->wait_handle ); + async->wait_handle = 0; + set_error( async->iosb->status ); + return 0; + } + if (async->iosb->status != STATUS_PENDING) { if (result) *result = async->iosb->result;
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/kernel32/tests/mailslot.c | 26 ++--- dlls/ntdll/unix/file.c | 66 +----------- server/mailslot.c | 192 ++++++++++++++++++++++++--------- server/protocol.def | 1 - 4 files changed, 152 insertions(+), 133 deletions(-)
diff --git a/dlls/kernel32/tests/mailslot.c b/dlls/kernel32/tests/mailslot.c index 23f1a14df20..9cc96c71caf 100644 --- a/dlls/kernel32/tests/mailslot.c +++ b/dlls/kernel32/tests/mailslot.c @@ -94,7 +94,6 @@ static int mailslot_test(void) SetLastError(0xdeadbeef); ret = ReadFile(hSlot, buffer, 0, &count, NULL); ok(!ret, "ReadFile should fail\n"); - todo_wine ok(GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %lu\n", GetLastError()); ok(count == 0, "expected 0, got %lu\n", count);
@@ -264,9 +263,7 @@ static int mailslot_test(void) ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ), "getmailslotinfo failed\n"); ok( dwNext == 1, "dwNext incorrect\n"); - todo_wine { ok( dwMsgCount == 2, "dwMsgCount incorrect\n"); - }
/* write a 3rd message with zero size */ ok( WriteFile( hWriter2, buffer, 0, &count, NULL), "3rd write failed\n"); @@ -276,8 +273,7 @@ static int mailslot_test(void) ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ), "getmailslotinfo failed\n"); ok( dwNext == 1, "dwNext incorrect\n"); - todo_wine - ok( dwMsgCount == 3, "dwMsgCount incorrect %lu\n", dwMsgCount); + ok( dwMsgCount == 3, "dwMsgCount incorrect %lu\n", dwMsgCount);
buffer[0]=buffer[1]=0;
@@ -295,9 +291,7 @@ static int mailslot_test(void) ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ), "getmailslotinfo failed\n"); ok( dwNext == 2, "dwNext incorrect\n"); - todo_wine { - ok( dwMsgCount == 2, "dwMsgCount incorrect %lu\n", dwMsgCount); - } + ok( dwMsgCount == 2, "dwMsgCount incorrect %lu\n", dwMsgCount);
/* read the second message */ ok( ReadFile( hSlot, buffer, sizeof buffer, &count, NULL), @@ -310,15 +304,11 @@ static int mailslot_test(void) ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ), "getmailslotinfo failed\n"); ok( dwNext == 0, "dwNext incorrect %lu\n", dwNext); - todo_wine { - ok( dwMsgCount == 1, "dwMsgCount incorrect %lu\n", dwMsgCount); - } + ok( dwMsgCount == 1, "dwMsgCount incorrect %lu\n", dwMsgCount);
/* read the 3rd (zero length) message */ - todo_wine { ok( ReadFile( hSlot, buffer, sizeof buffer, &count, NULL), "3rd slot read failed\n"); - } ok( count == 0, "failed to get 3rd message\n");
/* @@ -346,9 +336,9 @@ static int mailslot_test(void) io.Status = 0xdeadbeef; io.Information = 0xdeadbeef; ret = NtReadFile( hSlot, NULL, NULL, NULL, &io, buffer, 1, NULL, NULL ); - todo_wine ok( ret == STATUS_BUFFER_TOO_SMALL, "got %#x\n", ret ); - todo_wine ok( io.Status == 0xdeadbeef, "got status %#lx\n", io.Status ); - todo_wine ok( io.Information == 0xdeadbeef, "got size %Iu\n", io.Information ); + ok( ret == STATUS_BUFFER_TOO_SMALL, "got %#x\n", ret ); + ok( io.Status == 0xdeadbeef, "got status %#lx\n", io.Status ); + ok( io.Information == 0xdeadbeef, "got size %Iu\n", io.Information );
io.Status = 0xdeadbeef; io.Information = 0xdeadbeef; @@ -359,8 +349,8 @@ static int mailslot_test(void) ok( io.Information == sizeof(info), "got size %Iu\n", io.Information ); ok( !info.MaximumMessageSize, "got maximum size %lu\n", info.MaximumMessageSize ); ok( !info.MailslotQuota, "got quota %lu\n", info.MailslotQuota ); - todo_wine ok( info.NextMessageSize == 2, "got next size %lu\n", info.NextMessageSize ); - todo_wine ok( info.MessagesAvailable == 1, "got message count %lu\n", info.MessagesAvailable ); + ok( info.NextMessageSize == 2, "got next size %lu\n", info.NextMessageSize ); + ok( info.MessagesAvailable == 1, "got message count %lu\n", info.MessagesAvailable ); ok( !info.ReadTimeout.QuadPart, "got timeout %I64u\n", info.ReadTimeout.QuadPart );
io.Status = 0xdeadbeef; diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 15fdf2cb021..ec93f20d622 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -4521,44 +4521,6 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, } } break; - case FileMailslotQueryInformation: - { - FILE_MAILSLOT_QUERY_INFORMATION *info = ptr; - - SERVER_START_REQ( set_mailslot_info ) - { - req->handle = wine_server_obj_handle( handle ); - req->flags = 0; - status = wine_server_call( req ); - if (status == STATUS_SUCCESS) - { - info->MaximumMessageSize = reply->max_msgsize; - info->MailslotQuota = 0; - info->NextMessageSize = 0; - info->MessagesAvailable = 0; - info->ReadTimeout.QuadPart = reply->read_timeout; - } - } - SERVER_END_REQ; - if (!status) - { - char *tmpbuf; - ULONG size = info->MaximumMessageSize ? info->MaximumMessageSize : 0x10000; - if (size > 0x10000) size = 0x10000; - if ((tmpbuf = malloc( size ))) - { - if (needs_close) close( fd ); - if (!server_get_unix_fd( handle, FILE_READ_DATA, &fd, &needs_close, NULL, NULL )) - { - int res = recv( fd, tmpbuf, size, MSG_PEEK ); - info->MessagesAvailable = (res > 0); - info->NextMessageSize = (res >= 0) ? res : MAILSLOT_NO_MESSAGE; - } - free( tmpbuf ); - } - } - } - break; case FileNameInformation: { FILE_NAME_INFORMATION *info = ptr; @@ -5155,10 +5117,7 @@ static BOOL async_write_proc( void *user, ULONG_PTR *info, unsigned int *status &needs_close, &type, NULL ))) break;
- if (!fileio->count && type == FD_TYPE_MAILSLOT) - result = send( fd, fileio->buffer, 0, 0 ); - else - result = write( fd, &fileio->buffer[fileio->already], fileio->count - fileio->already ); + result = write( fd, &fileio->buffer[fileio->already], fileio->count - fileio->already );
if (needs_close) close( fd );
@@ -5363,20 +5322,6 @@ static unsigned int get_io_timeouts( HANDLE handle, enum server_fd_type type, UL } break; } - case FD_TYPE_MAILSLOT: - if (is_read) - { - timeouts->interval = 0; /* return as soon as we got something */ - SERVER_START_REQ( set_mailslot_info ) - { - req->handle = wine_server_obj_handle( handle ); - req->flags = 0; - if (!wine_server_call( req ) && reply->read_timeout != TIMEOUT_INFINITE) - timeouts->total = reply->read_timeout / -10000; - } - SERVER_END_REQ; - } - break; case FD_TYPE_SOCKET: case FD_TYPE_CHAR: if (is_read) timeouts->interval = 0; /* return as soon as we got something */ @@ -5427,7 +5372,6 @@ static NTSTATUS get_io_avail_mode( HANDLE handle, enum server_fd_type type, BOOL } break; } - case FD_TYPE_MAILSLOT: case FD_TYPE_SOCKET: case FD_TYPE_CHAR: *avail_mode = TRUE; @@ -5702,7 +5646,7 @@ NTSTATUS WINAPI NtReadFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, vo if (total) /* return with what we got so far */ status = STATUS_SUCCESS; else - status = (type == FD_TYPE_MAILSLOT) ? STATUS_IO_TIMEOUT : STATUS_TIMEOUT; + status = STATUS_TIMEOUT; goto done; } if (ret == -1 && errno != EINTR) @@ -5933,11 +5877,7 @@ NTSTATUS WINAPI NtWriteFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, v
for (;;) { - /* zero-length writes on sockets may not work with plain write(2) */ - if (!length && type == FD_TYPE_MAILSLOT) - result = send( unix_handle, buffer, 0, 0 ); - else - result = write( unix_handle, (const char *)buffer + total, length - total ); + result = write( unix_handle, (const char *)buffer + total, length - total );
if (result >= 0) { diff --git a/server/mailslot.c b/server/mailslot.c index 2d8697ec9bd..e0870ef5030 100644 --- a/server/mailslot.c +++ b/server/mailslot.c @@ -47,14 +47,21 @@ #include "thread.h" #include "request.h"
+struct mailslot_message +{ + struct list entry; + struct iosb *iosb; +}; + struct mailslot { struct object obj; struct fd *fd; - int write_fd; unsigned int max_msgsize; timeout_t read_timeout; struct list writers; + struct list messages; + struct async_queue read_q; };
/* mailslot functions */ @@ -91,21 +98,23 @@ static const struct object_ops mailslot_ops = };
static enum server_fd_type mailslot_get_fd_type( struct fd *fd ); -static void mailslot_queue_async( struct fd *fd, struct async *async, int type, int count ); +static void mailslot_read( struct fd *fd, struct async *async, file_pos_t pos ); +static void mailslot_write( struct fd *fd, struct async *async, file_pos_t pos ); +static void mailslot_get_file_info( struct fd *fd, obj_handle_t handle, unsigned int info_class );
static const struct fd_ops mailslot_fd_ops = { default_fd_get_poll_events, /* get_poll_events */ default_poll_event, /* poll_event */ mailslot_get_fd_type, /* get_fd_type */ - no_fd_read, /* read */ - no_fd_write, /* write */ + mailslot_read, /* read */ + mailslot_write, /* write */ no_fd_flush, /* flush */ - default_fd_get_file_info, /* get_file_info */ + mailslot_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ default_fd_ioctl, /* ioctl */ default_fd_cancel_async, /* cancel_async */ - mailslot_queue_async, /* queue_async */ + no_fd_queue_async, /* queue_async */ default_fd_reselect_async /* reselect_async */ };
@@ -150,14 +159,16 @@ static const struct object_ops mail_writer_ops = };
static enum server_fd_type mail_writer_get_fd_type( struct fd *fd ); +static void mail_writer_read( struct fd *fd, struct async *async, file_pos_t pos ); +static void mail_writer_write( struct fd *fd, struct async *async, file_pos_t pos );
static const struct fd_ops mail_writer_fd_ops = { default_fd_get_poll_events, /* get_poll_events */ default_poll_event, /* poll_event */ mail_writer_get_fd_type, /* get_fd_type */ - no_fd_read, /* read */ - no_fd_write, /* write */ + mail_writer_read, /* read */ + mail_writer_write, /* write */ no_fd_flush, /* flush */ default_fd_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ @@ -258,17 +269,29 @@ static const struct fd_ops mailslot_device_fd_ops = default_fd_reselect_async /* reselect_async */ };
+static struct mailslot_message *get_first_message( struct mailslot *mailslot ) +{ + if (list_empty( &mailslot->messages )) + return NULL; + + return LIST_ENTRY( list_head( &mailslot->messages ), struct mailslot_message, entry ); +} + static void mailslot_destroy( struct object *obj) { struct mailslot *mailslot = (struct mailslot *) obj; + struct mailslot_message *message;
- assert( mailslot->fd ); - - if (mailslot->write_fd != -1) + while ((message = get_first_message( mailslot ))) { - shutdown( mailslot->write_fd, SHUT_RDWR ); - close( mailslot->write_fd ); + list_remove( &message->entry ); + release_object( message->iosb ); + free( message ); } + + free_async_queue( &mailslot->read_q ); + + assert( mailslot->fd ); release_object( mailslot->fd ); }
@@ -283,7 +306,85 @@ static void mailslot_dump( struct object *obj, int verbose )
static enum server_fd_type mailslot_get_fd_type( struct fd *fd ) { - return FD_TYPE_MAILSLOT; + return FD_TYPE_DEVICE; +} + +static void reselect_mailslot( struct mailslot *mailslot ) +{ + struct mailslot_message *message; + struct async *async; + + while ((message = get_first_message( mailslot )) && (async = find_pending_async( &mailslot->read_q ))) + { + struct iosb *read_iosb = async_get_iosb( async ); + + if (read_iosb->out_size < message->iosb->in_size) + { + async_request_complete( async, STATUS_BUFFER_TOO_SMALL, 0, 0, NULL ); + } + else + { + async_request_complete( async, STATUS_SUCCESS, message->iosb->in_size, + message->iosb->in_size, message->iosb->in_data ); + message->iosb->in_data = NULL; + list_remove( &message->entry ); + release_object( message->iosb ); + free( message ); + } + + release_object( async ); + release_object( read_iosb ); + } +} + +static void mailslot_read( struct fd *fd, struct async *async, file_pos_t pos ) +{ + struct mailslot *mailslot = get_fd_user( fd ); + + if (mailslot->read_timeout != (timeout_t)-1) + async_set_timeout( async, mailslot->read_timeout ? mailslot->read_timeout : -1, STATUS_IO_TIMEOUT ); + queue_async( &mailslot->read_q, async ); + reselect_mailslot( mailslot ); + set_error( STATUS_PENDING ); +} + +static void mailslot_write( struct fd *fd, struct async *async, file_pos_t pos ) +{ + set_error( STATUS_INVALID_PARAMETER ); +} + +static void mailslot_get_file_info( struct fd *fd, obj_handle_t handle, unsigned int info_class ) +{ + struct mailslot *mailslot = get_fd_user( fd ); + + switch (info_class) + { + case FileMailslotQueryInformation: + { + FILE_MAILSLOT_QUERY_INFORMATION *info; + struct mailslot_message *message; + + if (get_reply_max_size() < sizeof(*info)) + { + set_error( STATUS_INFO_LENGTH_MISMATCH ); + return; + } + + if (!(info = set_reply_data_size( sizeof(*info) ))) return; + info->MaximumMessageSize = mailslot->max_msgsize; + info->MailslotQuota = 0; + info->MessagesAvailable = list_count( &mailslot->messages ); + if ((message = get_first_message( mailslot ))) + info->NextMessageSize = message->iosb->in_size; + else + info->NextMessageSize = MAILSLOT_NO_MESSAGE; + info->ReadTimeout.QuadPart = mailslot->read_timeout; + break; + } + + default: + default_fd_get_file_info( fd, handle, info_class ); + } }
static struct fd *mailslot_get_fd( struct object *obj ) @@ -318,7 +419,6 @@ static struct object *mailslot_open_file( struct object *obj, unsigned int acces { struct mailslot *mailslot = (struct mailslot *)obj; struct mail_writer *writer; - int unix_fd;
if (!(sharing & FILE_SHARE_READ)) { @@ -341,23 +441,15 @@ static struct object *mailslot_open_file( struct object *obj, unsigned int acces } }
- if ((unix_fd = dup( mailslot->write_fd )) == -1) - { - file_set_error(); - return NULL; - } if (!(writer = alloc_object( &mail_writer_ops ))) - { - close( unix_fd ); return NULL; - } grab_object( mailslot ); writer->mailslot = mailslot; writer->access = mail_writer_map_access( &writer->obj, access ); writer->sharing = sharing; list_add_head( &mailslot->writers, &writer->entry );
- if (!(writer->fd = create_anonymous_fd( &mail_writer_fd_ops, unix_fd, &writer->obj, options ))) + if (!(writer->fd = alloc_pseudo_fd( &mail_writer_fd_ops, &writer->obj, options ))) { release_object( writer ); return NULL; @@ -366,18 +458,6 @@ static struct object *mailslot_open_file( struct object *obj, unsigned int acces return &writer->obj; }
-static void mailslot_queue_async( struct fd *fd, struct async *async, int type, int count ) -{ - struct mailslot *mailslot = get_fd_user( fd ); - - assert(mailslot->obj.ops == &mailslot_ops); - - fd_queue_async( fd, async, type ); - async_set_timeout( async, mailslot->read_timeout ? mailslot->read_timeout : -1, - STATUS_IO_TIMEOUT ); - set_error( STATUS_PENDING ); -} - static void mailslot_device_dump( struct object *obj, int verbose ) { fputs( "Mailslot device\n", stderr ); @@ -478,30 +558,21 @@ static struct mailslot *create_mailslot( struct object *root, const struct security_descriptor *sd ) { struct mailslot *mailslot; - int fds[2];
if (!(mailslot = create_named_object( root, &mailslot_ops, name, attr, sd ))) return NULL;
mailslot->fd = NULL; - mailslot->write_fd = -1; mailslot->max_msgsize = max_msgsize; mailslot->read_timeout = read_timeout; list_init( &mailslot->writers ); + list_init( &mailslot->messages ); + init_async_queue( &mailslot->read_q );
- if (!socketpair( PF_UNIX, SOCK_DGRAM, 0, fds )) + if ((mailslot->fd = alloc_pseudo_fd( &mailslot_fd_ops, &mailslot->obj, FILE_SYNCHRONOUS_IO_NONALERT ))) { - fcntl( fds[0], F_SETFL, O_NONBLOCK ); - fcntl( fds[1], F_SETFL, O_NONBLOCK ); - shutdown( fds[0], SHUT_RD ); - mailslot->write_fd = fds[0]; - if ((mailslot->fd = create_anonymous_fd( &mailslot_fd_ops, fds[1], &mailslot->obj, - FILE_SYNCHRONOUS_IO_NONALERT ))) - { - allow_fd_caching( mailslot->fd ); - return mailslot; - } + allow_fd_caching( mailslot->fd ); + return mailslot; } - else file_set_error();
release_object( mailslot ); return NULL; @@ -523,7 +594,26 @@ static void mail_writer_destroy( struct object *obj)
static enum server_fd_type mail_writer_get_fd_type( struct fd *fd ) { - return FD_TYPE_MAILSLOT; + return FD_TYPE_DEVICE; +} + +static void mail_writer_read( struct fd *fd, struct async *async, file_pos_t pos ) +{ + set_error( STATUS_INVALID_PARAMETER ); +} + +static void mail_writer_write( struct fd *fd, struct async *async, file_pos_t pos ) +{ + struct mail_writer *writer = get_fd_user( fd ); + struct mailslot_message *message; + data_size_t size; + + if (!(message = mem_alloc( sizeof(*message) ))) return; + message->iosb = async_get_iosb( async ); + size = message->iosb->in_size; + list_add_tail( &writer->mailslot->messages, &message->entry ); + reselect_mailslot( writer->mailslot ); + async_request_complete( async, STATUS_SUCCESS, size, 0, NULL ); }
static struct fd *mail_writer_get_fd( struct object *obj ) diff --git a/server/protocol.def b/server/protocol.def index 3c6596aebe2..1616fd6bd0d 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1500,7 +1500,6 @@ enum server_fd_type FD_TYPE_DIR, /* directory */ FD_TYPE_SOCKET, /* socket */ FD_TYPE_SERIAL, /* serial port */ - FD_TYPE_MAILSLOT, /* mailslot */ FD_TYPE_CHAR, /* unspecified char device */ FD_TYPE_DEVICE, /* Windows device file */ FD_TYPE_NB_TYPES
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=146970
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
kernel32: mailslot.c:362: Test failed: got 0xc000000d mailslot.c:363: Test failed: got status 0xdeadbeef mailslot.c:364: Test failed: got size 3735928559 mailslot.c:365: Test failed: got maximum size 3435973836 mailslot.c:366: Test failed: got quota 3435973836 mailslot.c:367: Test failed: got next size 3435973836 mailslot.c:368: Test failed: got message count 3435973836 mailslot.c:369: Test failed: got timeout 14757395258967641292
=== w7u_adm (32 bit report) ===
kernel32: mailslot.c:362: Test failed: got 0xc000000d mailslot.c:363: Test failed: got status 0xdeadbeef mailslot.c:364: Test failed: got size 3735928559 mailslot.c:365: Test failed: got maximum size 3435973836 mailslot.c:366: Test failed: got quota 3435973836 mailslot.c:367: Test failed: got next size 3435973836 mailslot.c:368: Test failed: got message count 3435973836 mailslot.c:369: Test failed: got timeout 14757395258967641292
=== w7u_el (32 bit report) ===
kernel32: mailslot.c:362: Test failed: got 0xc000000d mailslot.c:363: Test failed: got status 0xdeadbeef mailslot.c:364: Test failed: got size 3735928559 mailslot.c:365: Test failed: got maximum size 3435973836 mailslot.c:366: Test failed: got quota 3435973836 mailslot.c:367: Test failed: got next size 3435973836 mailslot.c:368: Test failed: got message count 3435973836 mailslot.c:369: Test failed: got timeout 14757395258967641292
=== w7pro64 (64 bit report) ===
kernel32: mailslot.c:362: Test failed: got 0xc000000d mailslot.c:363: Test failed: got status 0xdeadbeef mailslot.c:364: Test failed: got size 3735928559 mailslot.c:365: Test failed: got maximum size 3435973836 mailslot.c:366: Test failed: got quota 3435973836 mailslot.c:367: Test failed: got next size 3435973836 mailslot.c:368: Test failed: got message count 3435973836 mailslot.c:369: Test failed: got timeout 14757395258967641292
=== debian11 (build log) ===
WineRunWineTest.pl:error: The task timed out
=== debian11b (32 bit WoW report) ===
kernel32: mailslot: Timeout
=== debian11b (64 bit WoW report) ===
kernel32: file.c:3309: Test succeeded inside todo block: expected type unknown got 0 mailslot: Timeout