Commit d85121f1 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Store the file access and options in the fd cache, and get rid of the dynamic flags.

This avoids server round-trips for all file I/O.
parent 7a9363a4
...@@ -526,7 +526,8 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, ...@@ -526,7 +526,8 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
PIO_STATUS_BLOCK io_status, void* buffer, ULONG length, PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
PLARGE_INTEGER offset, PULONG key) PLARGE_INTEGER offset, PULONG key)
{ {
int result, unix_handle, needs_close, flags, timeout_init_done = 0; int result, unix_handle, needs_close, timeout_init_done = 0;
unsigned int options;
struct io_timeouts timeouts; struct io_timeouts timeouts;
NTSTATUS status; NTSTATUS status;
ULONG total = 0; ULONG total = 0;
...@@ -538,7 +539,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, ...@@ -538,7 +539,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
if (!io_status) return STATUS_ACCESS_VIOLATION; if (!io_status) return STATUS_ACCESS_VIOLATION;
status = server_get_unix_fd( hFile, FILE_READ_DATA, &unix_handle, status = server_get_unix_fd( hFile, FILE_READ_DATA, &unix_handle,
&needs_close, &type, &flags ); &needs_close, &type, &options );
if (status) return status; if (status) return status;
if (type == FD_TYPE_FILE && offset && offset->QuadPart != (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */ ) if (type == FD_TYPE_FILE && offset && offset->QuadPart != (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */ )
...@@ -552,7 +553,8 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, ...@@ -552,7 +553,8 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
goto done; goto done;
} }
} }
if (!(flags & FD_FLAG_OVERLAPPED)) /* update file pointer position */ if (options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))
/* update file pointer position */
lseek( unix_handle, offset->QuadPart + result, SEEK_SET ); lseek( unix_handle, offset->QuadPart + result, SEEK_SET );
total = result; total = result;
...@@ -584,7 +586,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, ...@@ -584,7 +586,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
} }
} }
if (flags & FD_FLAG_OVERLAPPED) if (!(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
{ {
async_fileio_read *fileio; async_fileio_read *fileio;
BOOL avail_mode; BOOL avail_mode;
...@@ -761,7 +763,8 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent, ...@@ -761,7 +763,8 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
const void* buffer, ULONG length, const void* buffer, ULONG length,
PLARGE_INTEGER offset, PULONG key) PLARGE_INTEGER offset, PULONG key)
{ {
int result, unix_handle, needs_close, flags, timeout_init_done = 0; int result, unix_handle, needs_close, timeout_init_done = 0;
unsigned int options;
struct io_timeouts timeouts; struct io_timeouts timeouts;
NTSTATUS status; NTSTATUS status;
ULONG total = 0; ULONG total = 0;
...@@ -773,7 +776,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent, ...@@ -773,7 +776,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
if (!io_status) return STATUS_ACCESS_VIOLATION; if (!io_status) return STATUS_ACCESS_VIOLATION;
status = server_get_unix_fd( hFile, FILE_WRITE_DATA, &unix_handle, status = server_get_unix_fd( hFile, FILE_WRITE_DATA, &unix_handle,
&needs_close, &type, &flags ); &needs_close, &type, &options );
if (status) return status; if (status) return status;
if (type == FD_TYPE_FILE && offset && offset->QuadPart != (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */ ) if (type == FD_TYPE_FILE && offset && offset->QuadPart != (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */ )
...@@ -789,7 +792,8 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent, ...@@ -789,7 +792,8 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
} }
} }
if (!(flags & FD_FLAG_OVERLAPPED)) /* update file pointer position */ if (options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))
/* update file pointer position */
lseek( unix_handle, offset->QuadPart + result, SEEK_SET ); lseek( unix_handle, offset->QuadPart + result, SEEK_SET );
total = result; total = result;
...@@ -825,7 +829,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent, ...@@ -825,7 +829,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
} }
} }
if (flags & FD_FLAG_OVERLAPPED) if (!(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
{ {
async_fileio_write *fileio; async_fileio_write *fileio;
...@@ -1089,7 +1093,7 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc ...@@ -1089,7 +1093,7 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
case FSCTL_PIPE_PEEK: case FSCTL_PIPE_PEEK:
{ {
FILE_PIPE_PEEK_BUFFER *buffer = out_buffer; FILE_PIPE_PEEK_BUFFER *buffer = out_buffer;
int avail = 0, fd, needs_close, flags; int avail = 0, fd, needs_close;
if (out_size < FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data )) if (out_size < FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data ))
{ {
...@@ -1097,16 +1101,9 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc ...@@ -1097,16 +1101,9 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
break; break;
} }
if ((status = server_get_unix_fd( handle, FILE_READ_DATA, &fd, &needs_close, NULL, &flags ))) if ((status = server_get_unix_fd( handle, FILE_READ_DATA, &fd, &needs_close, NULL, NULL )))
break; break;
if (flags & FD_FLAG_RECV_SHUTDOWN)
{
if (needs_close) close( fd );
status = STATUS_PIPE_DISCONNECTED;
break;
}
#ifdef FIONREAD #ifdef FIONREAD
if (ioctl( fd, FIONREAD, &avail ) != 0) if (ioctl( fd, FIONREAD, &avail ) != 0)
{ {
......
...@@ -69,7 +69,7 @@ extern void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset ...@@ -69,7 +69,7 @@ extern void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset
extern void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ); extern void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset );
extern int server_remove_fd_from_cache( obj_handle_t handle ); extern int server_remove_fd_from_cache( obj_handle_t handle );
extern int server_get_unix_fd( obj_handle_t handle, unsigned int access, int *unix_fd, extern int server_get_unix_fd( obj_handle_t handle, unsigned int access, int *unix_fd,
int *needs_close, enum server_fd_type *type, int *flags ); int *needs_close, enum server_fd_type *type, unsigned int *options );
/* module handling */ /* module handling */
extern NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved ); extern NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved );
......
...@@ -464,7 +464,9 @@ static int receive_fd( obj_handle_t *handle ) ...@@ -464,7 +464,9 @@ static int receive_fd( obj_handle_t *handle )
struct fd_cache_entry struct fd_cache_entry
{ {
int fd; int fd;
enum server_fd_type type; enum server_fd_type type : 6;
unsigned int access : 2;
unsigned int options : 24;
}; };
#define FD_CACHE_BLOCK_SIZE (65536 / sizeof(struct fd_cache_entry)) #define FD_CACHE_BLOCK_SIZE (65536 / sizeof(struct fd_cache_entry))
...@@ -486,7 +488,8 @@ static inline unsigned int handle_to_index( obj_handle_t handle, unsigned int *e ...@@ -486,7 +488,8 @@ static inline unsigned int handle_to_index( obj_handle_t handle, unsigned int *e
* *
* Caller must hold fd_cache_section. * Caller must hold fd_cache_section.
*/ */
static int add_fd_to_cache( obj_handle_t handle, int fd, enum server_fd_type type ) static int add_fd_to_cache( obj_handle_t handle, int fd, enum server_fd_type type,
unsigned int access, unsigned int options )
{ {
unsigned int entry, idx = handle_to_index( handle, &entry ); unsigned int entry, idx = handle_to_index( handle, &entry );
int prev_fd; int prev_fd;
...@@ -511,6 +514,8 @@ static int add_fd_to_cache( obj_handle_t handle, int fd, enum server_fd_type typ ...@@ -511,6 +514,8 @@ static int add_fd_to_cache( obj_handle_t handle, int fd, enum server_fd_type typ
/* store fd+1 so that 0 can be used as the unset value */ /* store fd+1 so that 0 can be used as the unset value */
prev_fd = interlocked_xchg( &fd_cache[entry][idx].fd, fd + 1 ) - 1; prev_fd = interlocked_xchg( &fd_cache[entry][idx].fd, fd + 1 ) - 1;
fd_cache[entry][idx].type = type; fd_cache[entry][idx].type = type;
fd_cache[entry][idx].access = access;
fd_cache[entry][idx].options = options;
if (prev_fd != -1) close( prev_fd ); if (prev_fd != -1) close( prev_fd );
return 1; return 1;
} }
...@@ -521,7 +526,8 @@ static int add_fd_to_cache( obj_handle_t handle, int fd, enum server_fd_type typ ...@@ -521,7 +526,8 @@ static int add_fd_to_cache( obj_handle_t handle, int fd, enum server_fd_type typ
* *
* Caller must hold fd_cache_section. * Caller must hold fd_cache_section.
*/ */
static inline int get_cached_fd( obj_handle_t handle, enum server_fd_type *type ) static inline int get_cached_fd( obj_handle_t handle, enum server_fd_type *type,
unsigned int *access, unsigned int *options )
{ {
unsigned int entry, idx = handle_to_index( handle, &entry ); unsigned int entry, idx = handle_to_index( handle, &entry );
int fd = -1; int fd = -1;
...@@ -530,6 +536,8 @@ static inline int get_cached_fd( obj_handle_t handle, enum server_fd_type *type ...@@ -530,6 +536,8 @@ static inline int get_cached_fd( obj_handle_t handle, enum server_fd_type *type
{ {
fd = fd_cache[entry][idx].fd - 1; fd = fd_cache[entry][idx].fd - 1;
if (type) *type = fd_cache[entry][idx].type; if (type) *type = fd_cache[entry][idx].type;
if (access) *access = fd_cache[entry][idx].access;
if (options) *options = fd_cache[entry][idx].options;
} }
return fd; return fd;
} }
...@@ -555,46 +563,50 @@ int server_remove_fd_from_cache( obj_handle_t handle ) ...@@ -555,46 +563,50 @@ int server_remove_fd_from_cache( obj_handle_t handle )
* *
* The returned unix_fd should be closed iff needs_close is non-zero. * The returned unix_fd should be closed iff needs_close is non-zero.
*/ */
int server_get_unix_fd( obj_handle_t handle, unsigned int access, int *unix_fd, int server_get_unix_fd( obj_handle_t handle, unsigned int wanted_access, int *unix_fd,
int *needs_close, enum server_fd_type *type, int *flags ) int *needs_close, enum server_fd_type *type, unsigned int *options )
{ {
sigset_t sigset; sigset_t sigset;
obj_handle_t fd_handle; obj_handle_t fd_handle;
int ret = 0, removable = 0, fd; int ret = 0, fd;
unsigned int access;
*unix_fd = -1; *unix_fd = -1;
*needs_close = 0; *needs_close = 0;
wanted_access &= FILE_READ_DATA | FILE_WRITE_DATA;
server_enter_uninterrupted_section( &fd_cache_section, &sigset ); server_enter_uninterrupted_section( &fd_cache_section, &sigset );
fd = get_cached_fd( handle, type ); fd = get_cached_fd( handle, type, &access, options );
if (fd != -1 && !flags) goto done; if (fd != -1) goto done;
SERVER_START_REQ( get_handle_fd ) SERVER_START_REQ( get_handle_fd )
{ {
req->handle = handle; req->handle = handle;
req->access = access;
req->cached = (fd != -1);
if (!(ret = wine_server_call( req ))) if (!(ret = wine_server_call( req )))
{ {
removable = reply->flags & FD_FLAG_REMOVABLE;
if (type) *type = reply->type; if (type) *type = reply->type;
if (flags) *flags = reply->flags; if (options) *options = reply->options;
if (fd == -1) access = reply->access;
if ((fd = receive_fd( &fd_handle )) != -1)
{ {
if ((fd = receive_fd( &fd_handle )) != -1) assert( fd_handle == handle );
{ *needs_close = (reply->removable ||
assert( fd_handle == handle ); !add_fd_to_cache( handle, fd, reply->type,
*needs_close = removable || !add_fd_to_cache( handle, fd, reply->type ); reply->access, reply->options ));
}
else ret = STATUS_TOO_MANY_OPENED_FILES;
} }
else ret = STATUS_TOO_MANY_OPENED_FILES;
} }
} }
SERVER_END_REQ; SERVER_END_REQ;
done: done:
server_leave_uninterrupted_section( &fd_cache_section, &sigset ); server_leave_uninterrupted_section( &fd_cache_section, &sigset );
if (!ret && ((access & wanted_access) != wanted_access))
{
ret = STATUS_ACCESS_DENIED;
if (*needs_close) close( fd );
}
if (!ret) *unix_fd = fd; if (!ret) *unix_fd = fd;
return ret; return ret;
} }
...@@ -642,14 +654,15 @@ int wine_server_fd_to_handle( int fd, unsigned int access, unsigned int attribut ...@@ -642,14 +654,15 @@ int wine_server_fd_to_handle( int fd, unsigned int access, unsigned int attribut
* handle [I] Wine file handle. * handle [I] Wine file handle.
* access [I] Win32 file access rights requested. * access [I] Win32 file access rights requested.
* unix_fd [O] Address where Unix file descriptor will be stored. * unix_fd [O] Address where Unix file descriptor will be stored.
* flags [O] Address where the Unix flags associated with file will be stored. Optional. * options [O] Address where the file open options will be stored. Optional.
* *
* RETURNS * RETURNS
* NTSTATUS code * NTSTATUS code
*/ */
int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *unix_fd, int *flags ) int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *unix_fd,
unsigned int *options )
{ {
int needs_close, ret = server_get_unix_fd( handle, access, unix_fd, &needs_close, NULL, flags ); int needs_close, ret = server_get_unix_fd( handle, access, unix_fd, &needs_close, NULL, options );
if (!ret && !needs_close) if (!ret && !needs_close)
{ {
......
...@@ -384,10 +384,10 @@ static inline unsigned int set_error( unsigned int err ) ...@@ -384,10 +384,10 @@ static inline unsigned int set_error( unsigned int err )
return err; return err;
} }
static inline int get_sock_fd( SOCKET s, DWORD access, int *flags ) static inline int get_sock_fd( SOCKET s, DWORD access, unsigned int *options )
{ {
int fd; int fd;
if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, flags ) )) if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, options ) ))
return -1; return -1;
return fd; return fd;
} }
...@@ -2754,8 +2754,8 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -2754,8 +2754,8 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ) LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
{ {
unsigned int i; unsigned int i, options;
int n, fd, err = WSAENOTSOCK, flags, ret; int n, fd, err = WSAENOTSOCK, ret;
struct iovec* iovec; struct iovec* iovec;
struct ws2_async *wsa; struct ws2_async *wsa;
IO_STATUS_BLOCK* iosb; IO_STATUS_BLOCK* iosb;
...@@ -2764,17 +2764,11 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -2764,17 +2764,11 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
s, lpBuffers, dwBufferCount, dwFlags, s, lpBuffers, dwBufferCount, dwFlags,
to, tolen, lpOverlapped, lpCompletionRoutine); to, tolen, lpOverlapped, lpCompletionRoutine);
fd = get_sock_fd( s, FILE_WRITE_DATA, &flags ); fd = get_sock_fd( s, FILE_WRITE_DATA, &options );
TRACE( "fd=%d, flags=%x\n", fd, flags ); TRACE( "fd=%d, options=%x\n", fd, options );
if ( fd == -1 ) return SOCKET_ERROR; if ( fd == -1 ) return SOCKET_ERROR;
if (flags & FD_FLAG_SEND_SHUTDOWN)
{
WSASetLastError( WSAESHUTDOWN );
goto err_close;
}
if ( !lpNumberOfBytesSent ) if ( !lpNumberOfBytesSent )
{ {
err = WSAEFAULT; err = WSAEFAULT;
...@@ -2795,7 +2789,8 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -2795,7 +2789,8 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
iovec[i].iov_len = lpBuffers[i].len; iovec[i].iov_len = lpBuffers[i].len;
} }
if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED ) if ( (lpOverlapped || lpCompletionRoutine) &&
!(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
{ {
wsa = WS2_make_async( s, ws2m_write, iovec, dwBufferCount, wsa = WS2_make_async( s, ws2m_write, iovec, dwBufferCount,
&dwFlags, (struct WS_sockaddr*) to, &tolen, &dwFlags, (struct WS_sockaddr*) to, &tolen,
...@@ -3175,11 +3170,11 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, ...@@ -3175,11 +3170,11 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
*/ */
int WINAPI WS_shutdown(SOCKET s, int how) int WINAPI WS_shutdown(SOCKET s, int how)
{ {
int fd, flags, err = WSAENOTSOCK; int fd, err = WSAENOTSOCK;
unsigned int clear_flags = 0; unsigned int options, clear_flags = 0;
fd = get_sock_fd( s, 0, &flags ); fd = get_sock_fd( s, 0, &options );
TRACE("socket %04x, how %i %x\n", s, how, flags ); TRACE("socket %04x, how %i %x\n", s, how, options );
if (fd == -1) if (fd == -1)
return SOCKET_ERROR; return SOCKET_ERROR;
...@@ -3198,8 +3193,8 @@ int WINAPI WS_shutdown(SOCKET s, int how) ...@@ -3198,8 +3193,8 @@ int WINAPI WS_shutdown(SOCKET s, int how)
clear_flags |= FD_WINE_LISTENING; clear_flags |= FD_WINE_LISTENING;
} }
if ( flags & FD_FLAG_OVERLAPPED ) { if (!(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
{
switch ( how ) switch ( how )
{ {
case SD_RECEIVE: case SD_RECEIVE:
...@@ -4265,8 +4260,8 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -4265,8 +4260,8 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ) LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
{ {
unsigned int i; unsigned int i, options;
int n, fd, err = WSAENOTSOCK, flags, ret; int n, fd, err = WSAENOTSOCK, ret;
struct iovec* iovec; struct iovec* iovec;
struct ws2_async *wsa; struct ws2_async *wsa;
IO_STATUS_BLOCK* iosb; IO_STATUS_BLOCK* iosb;
...@@ -4276,17 +4271,11 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -4276,17 +4271,11 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
(lpFromlen ? *lpFromlen : -1), (lpFromlen ? *lpFromlen : -1),
lpOverlapped, lpCompletionRoutine); lpOverlapped, lpCompletionRoutine);
fd = get_sock_fd( s, FILE_READ_DATA, &flags ); fd = get_sock_fd( s, FILE_READ_DATA, &options );
TRACE( "fd=%d, flags=%x\n", fd, flags ); TRACE( "fd=%d, options=%x\n", fd, options );
if (fd == -1) return SOCKET_ERROR; if (fd == -1) return SOCKET_ERROR;
if (flags & FD_FLAG_RECV_SHUTDOWN)
{
WSASetLastError( WSAESHUTDOWN );
goto err_close;
}
iovec = HeapAlloc( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) ); iovec = HeapAlloc( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
if ( !iovec ) if ( !iovec )
{ {
...@@ -4300,7 +4289,8 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -4300,7 +4289,8 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
iovec[i].iov_len = lpBuffers[i].len; iovec[i].iov_len = lpBuffers[i].len;
} }
if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED ) if ( (lpOverlapped || lpCompletionRoutine) &&
!(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
{ {
wsa = WS2_make_async( s, ws2m_read, iovec, dwBufferCount, wsa = WS2_make_async( s, ws2m_read, iovec, dwBufferCount,
lpFlags, lpFrom, lpFromlen, lpFlags, lpFrom, lpFromlen,
......
...@@ -52,7 +52,7 @@ struct __server_request_info ...@@ -52,7 +52,7 @@ struct __server_request_info
extern unsigned int wine_server_call( void *req_ptr ); extern unsigned int wine_server_call( void *req_ptr );
extern void wine_server_send_fd( int fd ); extern void wine_server_send_fd( int fd );
extern int wine_server_fd_to_handle( int fd, unsigned int access, unsigned int attributes, obj_handle_t *handle ); extern int wine_server_fd_to_handle( int fd, unsigned int access, unsigned int attributes, obj_handle_t *handle );
extern int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *unix_fd, int *flags ); extern int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *unix_fd, unsigned int *options );
extern void wine_server_release_fd( obj_handle_t handle, int unix_fd ); extern void wine_server_release_fd( obj_handle_t handle, int unix_fd );
/* do a server call and set the last error code */ /* do a server call and set the last error code */
......
...@@ -1067,14 +1067,14 @@ struct get_handle_fd_request ...@@ -1067,14 +1067,14 @@ struct get_handle_fd_request
{ {
struct request_header __header; struct request_header __header;
obj_handle_t handle; obj_handle_t handle;
unsigned int access;
int cached;
}; };
struct get_handle_fd_reply struct get_handle_fd_reply
{ {
struct reply_header __header; struct reply_header __header;
int type; int type;
int flags; int removable;
unsigned int access;
unsigned int options;
}; };
enum server_fd_type enum server_fd_type
{ {
...@@ -1088,13 +1088,7 @@ enum server_fd_type ...@@ -1088,13 +1088,7 @@ enum server_fd_type
FD_TYPE_DEVICE, FD_TYPE_DEVICE,
FD_TYPE_NB_TYPES FD_TYPE_NB_TYPES
}; };
#define FD_FLAG_OVERLAPPED 0x01
#define FD_FLAG_TIMEOUT 0x02
#define FD_FLAG_RECV_SHUTDOWN 0x04
#define FD_FLAG_SEND_SHUTDOWN 0x08
#define FD_FLAG_AVAILABLE 0x10 /* in overlap read/write operation,
* only handle available data (don't wait) */
#define FD_FLAG_REMOVABLE 0x20
struct flush_file_request struct flush_file_request
...@@ -4677,6 +4671,6 @@ union generic_reply ...@@ -4677,6 +4671,6 @@ union generic_reply
struct allocate_locally_unique_id_reply allocate_locally_unique_id_reply; struct allocate_locally_unique_id_reply allocate_locally_unique_id_reply;
}; };
#define SERVER_PROTOCOL_VERSION 291 #define SERVER_PROTOCOL_VERSION 292
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
...@@ -1905,19 +1905,18 @@ DECL_HANDLER(get_handle_fd) ...@@ -1905,19 +1905,18 @@ DECL_HANDLER(get_handle_fd)
{ {
struct fd *fd; struct fd *fd;
if ((fd = get_handle_fd_obj( current->process, req->handle, req->access ))) if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
{ {
reply->flags = 0;
reply->type = fd->fd_ops->get_fd_type( fd ); reply->type = fd->fd_ops->get_fd_type( fd );
if (reply->type != FD_TYPE_INVALID) if (reply->type != FD_TYPE_INVALID)
{ {
if (!(fd->options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))) int unix_fd = get_unix_fd( fd );
reply->flags |= FD_FLAG_OVERLAPPED; if (unix_fd != -1)
if (is_fd_removable(fd)) reply->flags |= FD_FLAG_REMOVABLE;
if (!req->cached)
{ {
int unix_fd = get_unix_fd( fd ); send_client_fd( current->process, unix_fd, req->handle );
if (unix_fd != -1) send_client_fd( current->process, unix_fd, req->handle ); reply->removable = is_fd_removable(fd);
reply->options = fd->options;
reply->access = get_handle_access( current->process, req->handle );
} }
} }
else set_error( STATUS_OBJECT_TYPE_MISMATCH ); else set_error( STATUS_OBJECT_TYPE_MISMATCH );
......
...@@ -883,11 +883,11 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT }; ...@@ -883,11 +883,11 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
/* Get a Unix fd to access a file */ /* Get a Unix fd to access a file */
@REQ(get_handle_fd) @REQ(get_handle_fd)
obj_handle_t handle; /* handle to the file */ obj_handle_t handle; /* handle to the file */
unsigned int access; /* wanted access rights */
int cached; /* is it cached on the client already? */
@REPLY @REPLY
int type; /* file type (see below) */ int type; /* file type (see below) */
int flags; /* file read/write flags (see below) */ int removable; /* is file removable? */
unsigned int access; /* file access rights */
unsigned int options; /* file open options */
@END @END
enum server_fd_type enum server_fd_type
{ {
...@@ -901,13 +901,7 @@ enum server_fd_type ...@@ -901,13 +901,7 @@ enum server_fd_type
FD_TYPE_DEVICE, /* Windows device file */ FD_TYPE_DEVICE, /* Windows device file */
FD_TYPE_NB_TYPES FD_TYPE_NB_TYPES
}; };
#define FD_FLAG_OVERLAPPED 0x01 /* fd opened in overlapped mode */
#define FD_FLAG_TIMEOUT 0x02 /* read/write is synchronous */
#define FD_FLAG_RECV_SHUTDOWN 0x04
#define FD_FLAG_SEND_SHUTDOWN 0x08
#define FD_FLAG_AVAILABLE 0x10 /* in overlap read/write operation,
* only handle available data (don't wait) */
#define FD_FLAG_REMOVABLE 0x20 /* is it on a removable device? */
/* Flush a file buffers */ /* Flush a file buffers */
@REQ(flush_file) @REQ(flush_file)
......
...@@ -1274,15 +1274,15 @@ static void dump_alloc_file_handle_reply( const struct alloc_file_handle_reply * ...@@ -1274,15 +1274,15 @@ static void dump_alloc_file_handle_reply( const struct alloc_file_handle_reply *
static void dump_get_handle_fd_request( const struct get_handle_fd_request *req ) static void dump_get_handle_fd_request( const struct get_handle_fd_request *req )
{ {
fprintf( stderr, " handle=%p,", req->handle ); fprintf( stderr, " handle=%p", req->handle );
fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " cached=%d", req->cached );
} }
static void dump_get_handle_fd_reply( const struct get_handle_fd_reply *req ) static void dump_get_handle_fd_reply( const struct get_handle_fd_reply *req )
{ {
fprintf( stderr, " type=%d,", req->type ); fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " flags=%d", req->flags ); fprintf( stderr, " removable=%d,", req->removable );
fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " options=%08x", req->options );
} }
static void dump_flush_file_request( const struct flush_file_request *req ) static void dump_flush_file_request( const struct flush_file_request *req )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment