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.
This commit is contained in:
parent
7a9363a4d4
commit
d85121f199
|
@ -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,
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
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 )
|
||||||
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
|
||||||
*
|
*
|
||||||
* 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
|
||||||
/* 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
|
||||||
*
|
*
|
||||||
* 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
|
||||||
{
|
{
|
||||||
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 )
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* 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 )
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
(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,
|
||||||
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
|
||||||
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
|
||||||
{
|
{
|
||||||
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
|
||||||
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
|
||||||
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 */
|
||||||
|
|
15
server/fd.c
15
server/fd.c
|
@ -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 };
|
||||||
/* 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
|
||||||
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 *
|
||||||
|
|
||||||
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 )
|
||||||
|
|
Loading…
Reference in New Issue