Module: wine Branch: master Commit: c702a91a3ca605637577281f78a1dc61dd067e06 URL: http://source.winehq.org/git/wine.git/?a=commit;h=c702a91a3ca605637577281f78...
Author: Andrey Turkin andrey.turkin@gmail.com Date: Sat Nov 10 01:11:48 2007 +0300
server: Allow async i/o operations to send completion messages.
---
dlls/ntdll/directory.c | 1 + dlls/ntdll/file.c | 26 ++++++++++++++++++++++---- dlls/ws2_32/socket.c | 3 +++ include/wine/server_protocol.h | 3 ++- server/async.c | 6 ++++++ server/completion.c | 2 +- server/fd.c | 7 +++++++ server/file.h | 4 +++- server/protocol.def | 1 + 9 files changed, 46 insertions(+), 7 deletions(-)
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index 9288d31..6891949 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -2356,6 +2356,7 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event, req->async.arg = info; req->async.apc = read_changes_user_apc; req->async.event = Event; + req->async.cvalue = 0; status = wine_server_call( req ); } SERVER_END_REQ; diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 7b64b67..a3a4af1 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -650,6 +650,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, req->async.arg = fileio; req->async.apc = fileio_apc; req->async.event = hEvent; + req->async.cvalue = 0; status = wine_server_call( req ); } SERVER_END_REQ; @@ -879,6 +880,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent, req->async.arg = fileio; req->async.apc = fileio_apc; req->async.event = hEvent; + req->async.cvalue = 0; status = wine_server_call( req ); } SERVER_END_REQ; @@ -1005,6 +1007,7 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event, req->async.arg = async; req->async.apc = (apc || event) ? ioctl_apc : NULL; req->async.event = event; + req->async.cvalue = 0; wine_server_add_data( req, in_buffer, in_size ); wine_server_set_reply( req, out_buffer, out_size ); if (!(status = wine_server_call( req ))) @@ -1061,7 +1064,7 @@ NTSTATUS WINAPI NtDeviceIoControlFile(HANDLE handle, HANDLE event, PVOID out_buffer, ULONG out_size) { ULONG device = (code >> 16); - NTSTATUS status; + NTSTATUS status = STATUS_NOT_SUPPORTED;
TRACE("(%p,%p,%p,%p,%p,0x%08x,%p,0x%08x,%p,0x%08x)\n", handle, event, apc, apc_context, io, code, @@ -1085,11 +1088,12 @@ NTSTATUS WINAPI NtDeviceIoControlFile(HANDLE handle, HANDLE event, status = TAPE_DeviceIoControl(handle, event, apc, apc_context, io, code, in_buffer, in_size, out_buffer, out_size); break; - default: + } + + if (status == STATUS_NOT_SUPPORTED) status = server_ioctl_file( handle, event, apc, apc_context, io, code, in_buffer, in_size, out_buffer, out_size ); - break; - } + if (status != STATUS_PENDING) io->u.Status = status; return status; } @@ -1807,6 +1811,16 @@ static inline void get_device_info_fstatfs( FILE_FS_DEVICE_INFORMATION *info, co } #endif
+static inline int is_device_placeholder( int fd ) +{ + static const char wine_placeholder[] = "Wine device placeholder"; + char buffer[sizeof(wine_placeholder)-1]; + + if (pread( fd, buffer, sizeof(wine_placeholder) - 1, 0 ) != sizeof(wine_placeholder) - 1) + return 0; + return !memcmp( buffer, wine_placeholder, sizeof(wine_placeholder) - 1 ); +} + /****************************************************************************** * get_device_info * @@ -1847,6 +1861,10 @@ static NTSTATUS get_device_info( int fd, FILE_FS_DEVICE_INFORMATION *info ) { info->DeviceType = FILE_DEVICE_NAMED_PIPE; } + else if (is_device_placeholder( fd )) + { + info->DeviceType = FILE_DEVICE_DISK; + } else /* regular file or directory */ { #if defined(linux) && defined(HAVE_FSTATFS) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index f4111cd..5d51311 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1324,6 +1324,7 @@ static int WS2_register_async_shutdown( SOCKET s, int type ) req->async.iosb = &wsa->local_iosb; req->async.arg = wsa; req->async.apc = ws2_async_apc; + req->async.cvalue = 0; status = wine_server_call( req ); } SERVER_END_REQ; @@ -2688,6 +2689,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, req->async.arg = wsa; req->async.apc = ws2_async_apc; req->async.event = lpCompletionRoutine ? 0 : lpOverlapped->hEvent; + req->async.cvalue = 0; err = wine_server_call( req ); } SERVER_END_REQ; @@ -4201,6 +4203,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, req->async.arg = wsa; req->async.apc = ws2_async_apc; req->async.event = lpCompletionRoutine ? 0 : lpOverlapped->hEvent; + req->async.cvalue = 0; err = wine_server_call( req ); } SERVER_END_REQ; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 913f2a1..410b802 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -163,6 +163,7 @@ typedef struct void *arg; void *apc; obj_handle_t event; + unsigned long cvalue; } async_data_t;
@@ -4885,6 +4886,6 @@ union generic_reply struct set_completion_info_reply set_completion_info_reply; };
-#define SERVER_PROTOCOL_VERSION 328 +#define SERVER_PROTOCOL_VERSION 329
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/async.c b/server/async.c index 3a99f80..98d6075 100644 --- a/server/async.c +++ b/server/async.c @@ -144,6 +144,10 @@ void async_terminate( struct async *async, unsigned int status ) return; }
+ /* send error completion event */ + if (status != STATUS_ALERTED && async->data.cvalue && async->queue && async->queue->fd) + fd_add_completion( async->queue->fd, async->data.cvalue, status, 0 ); + memset( &data, 0, sizeof(data) ); data.type = APC_ASYNC_IO; data.async_io.func = async->data.callback; @@ -251,6 +255,8 @@ void async_set_result( struct object *obj, unsigned int status ) if (async->timeout) remove_timeout_user( async->timeout ); async->timeout = NULL; async->status = status; + if (async->data.cvalue && async->queue && async->queue->fd) + fd_add_completion( async->queue->fd, async->data.cvalue, status, 0 ); /* TODO pass Information field */ if (async->data.apc) { apc_call_t data; diff --git a/server/completion.c b/server/completion.c index bff2ada..96aaacc 100644 --- a/server/completion.c +++ b/server/completion.c @@ -132,7 +132,7 @@ struct completion *get_completion_obj( struct process *process, obj_handle_t han return (struct completion *) get_handle_obj( process, handle, access, &completion_ops ); }
-static void add_completion( struct completion *completion, unsigned long ckey, unsigned long cvalue, unsigned int status, unsigned long information ) +void add_completion( struct completion *completion, unsigned long ckey, unsigned long cvalue, unsigned int status, unsigned long information ) { struct comp_msg *msg = mem_alloc( sizeof( *msg ) );
diff --git a/server/fd.c b/server/fd.c index dc292cb..cb3aea8 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1919,6 +1919,13 @@ static struct fd *get_handle_fd_obj( struct process *process, obj_handle_t handl return fd; }
+/* add a completion result to a completion queue attached to the fd */ +void fd_add_completion( struct fd *fd, unsigned long cvalue, unsigned int status, unsigned long information ) +{ + if (fd->completion) + add_completion( fd->completion, fd->comp_key, cvalue, status, information ); +} + /* flush a file buffers */ DECL_HANDLER(flush_file) { diff --git a/server/file.h b/server/file.h index d6295d9..dbf0930 100644 --- a/server/file.h +++ b/server/file.h @@ -122,7 +122,8 @@ extern struct object *create_dir_obj( struct fd *fd );
/* completion */
-struct completion *get_completion_obj( struct process *process, obj_handle_t handle, unsigned int access ); +extern struct completion *get_completion_obj( struct process *process, obj_handle_t handle, unsigned int access ); +extern void add_completion( struct completion *completion, unsigned long ckey, unsigned long cvalue, unsigned int status, unsigned long information );
/* serial port functions */
@@ -139,6 +140,7 @@ extern void async_set_result( struct object *obj, unsigned int status ); extern int async_waiting( struct async_queue *queue ); extern void async_terminate( struct async *async, unsigned int status ); extern void async_wake_up( struct async_queue *queue, unsigned int status ); +extern void fd_add_completion( struct fd *fd, unsigned long cvalue, unsigned int status, unsigned long information );
/* access rights that require Unix read permission */ #define FILE_UNIX_READ_ACCESS (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA) diff --git a/server/protocol.def b/server/protocol.def index 90e943b..93e4887 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -179,6 +179,7 @@ typedef struct void *arg; /* opaque user data to pass to callback */ void *apc; /* user apc to call */ obj_handle_t event; /* event to signal when done */ + unsigned long cvalue; /* completion value to use for completion events */ } async_data_t;
/* structures for extra message data */