server: Return an fd type in the get_handle_fd request.
This commit is contained in:
parent
0427c0ded3
commit
8930427b21
|
@ -844,8 +844,21 @@ struct get_handle_fd_request
|
|||
struct get_handle_fd_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
int type;
|
||||
int flags;
|
||||
};
|
||||
enum server_fd_type
|
||||
{
|
||||
FD_TYPE_INVALID,
|
||||
FD_TYPE_FILE,
|
||||
FD_TYPE_DIR,
|
||||
FD_TYPE_SOCKET,
|
||||
FD_TYPE_SERIAL,
|
||||
FD_TYPE_PIPE,
|
||||
FD_TYPE_MAILSLOT,
|
||||
FD_TYPE_DEVICE,
|
||||
FD_TYPE_NB_TYPES
|
||||
};
|
||||
#define FD_FLAG_OVERLAPPED 0x01
|
||||
#define FD_FLAG_TIMEOUT 0x02
|
||||
#define FD_FLAG_RECV_SHUTDOWN 0x04
|
||||
|
@ -4404,6 +4417,6 @@ union generic_reply
|
|||
struct query_symlink_reply query_symlink_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 259
|
||||
#define SERVER_PROTOCOL_VERSION 260
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -182,7 +182,7 @@ static const struct object_ops dir_ops =
|
|||
};
|
||||
|
||||
static int dir_get_poll_events( struct fd *fd );
|
||||
static int dir_get_info( struct fd *fd );
|
||||
static enum server_fd_type dir_get_info( struct fd *fd, int *flags );
|
||||
static void dir_cancel_async( struct fd *fd );
|
||||
|
||||
static const struct fd_ops dir_fd_ops =
|
||||
|
@ -372,9 +372,10 @@ static int dir_get_poll_events( struct fd *fd )
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dir_get_info( struct fd *fd )
|
||||
static enum server_fd_type dir_get_info( struct fd *fd, int *flags )
|
||||
{
|
||||
return 0;
|
||||
*flags = 0;
|
||||
return FD_TYPE_DIR;
|
||||
}
|
||||
|
||||
static void dir_cancel_async( struct fd *fd )
|
||||
|
@ -550,14 +551,13 @@ static struct inode *inode_from_name( struct inode *inode, const char *name )
|
|||
|
||||
static int inotify_get_poll_events( struct fd *fd );
|
||||
static void inotify_poll_event( struct fd *fd, int event );
|
||||
static int inotify_get_info( struct fd *fd );
|
||||
|
||||
static const struct fd_ops inotify_fd_ops =
|
||||
{
|
||||
inotify_get_poll_events, /* get_poll_events */
|
||||
inotify_poll_event, /* poll_event */
|
||||
no_flush, /* flush */
|
||||
inotify_get_info, /* get_file_info */
|
||||
no_get_file_info, /* get_file_info */
|
||||
default_fd_queue_async, /* queue_async */
|
||||
default_fd_cancel_async, /* cancel_async */
|
||||
};
|
||||
|
@ -823,11 +823,6 @@ static void inotify_poll_event( struct fd *fd, int event )
|
|||
}
|
||||
}
|
||||
|
||||
static int inotify_get_info( struct fd *fd )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct fd *create_inotify_fd( void )
|
||||
{
|
||||
int unix_fd;
|
||||
|
|
25
server/fd.c
25
server/fd.c
|
@ -1774,9 +1774,10 @@ void fd_queue_async_timeout( struct fd *fd, void *apc, void *user, void *io_sb,
|
|||
const struct timeval *timeout )
|
||||
{
|
||||
struct list *queue;
|
||||
int events;
|
||||
int events, flags;
|
||||
|
||||
if (!(fd->fd_ops->get_file_info( fd ) & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT)))
|
||||
fd->fd_ops->get_file_info( fd, &flags );
|
||||
if (!(flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT)))
|
||||
{
|
||||
set_error( STATUS_INVALID_HANDLE );
|
||||
return;
|
||||
|
@ -1824,10 +1825,10 @@ int no_flush( struct fd *fd, struct event **event )
|
|||
}
|
||||
|
||||
/* default get_file_info() routine */
|
||||
int no_get_file_info( struct fd *fd )
|
||||
enum server_fd_type no_get_file_info( struct fd *fd, int *flags )
|
||||
{
|
||||
set_error( STATUS_OBJECT_TYPE_MISMATCH );
|
||||
return 0;
|
||||
*flags = 0;
|
||||
return FD_TYPE_INVALID;
|
||||
}
|
||||
|
||||
/* default queue_async() routine */
|
||||
|
@ -1955,13 +1956,17 @@ DECL_HANDLER(get_handle_fd)
|
|||
|
||||
if ((fd = get_handle_fd_obj( current->process, req->handle, req->access )))
|
||||
{
|
||||
if (!req->cached)
|
||||
reply->type = fd->fd_ops->get_file_info( fd, &reply->flags );
|
||||
if (reply->type != FD_TYPE_INVALID)
|
||||
{
|
||||
int unix_fd = get_unix_fd( fd );
|
||||
if (unix_fd != -1) send_client_fd( current->process, unix_fd, req->handle );
|
||||
if (fd->inode && fd->inode->device->removable) reply->flags |= FD_FLAG_REMOVABLE;
|
||||
if (!req->cached)
|
||||
{
|
||||
int unix_fd = get_unix_fd( fd );
|
||||
if (unix_fd != -1) send_client_fd( current->process, unix_fd, req->handle );
|
||||
}
|
||||
}
|
||||
reply->flags = fd->fd_ops->get_file_info( fd );
|
||||
if (fd->inode && fd->inode->device->removable) reply->flags |= FD_FLAG_REMOVABLE;
|
||||
else set_error( STATUS_OBJECT_TYPE_MISMATCH );
|
||||
release_object( fd );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ static void file_destroy( struct object *obj );
|
|||
|
||||
static int file_get_poll_events( struct fd *fd );
|
||||
static int file_flush( struct fd *fd, struct event **event );
|
||||
static int file_get_info( struct fd *fd );
|
||||
static enum server_fd_type file_get_info( struct fd *fd, int *flags );
|
||||
|
||||
static const struct object_ops file_ops =
|
||||
{
|
||||
|
@ -238,12 +238,13 @@ static int file_flush( struct fd *fd, struct event **event )
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int file_get_info( struct fd *fd )
|
||||
static enum server_fd_type file_get_info( struct fd *fd, int *flags )
|
||||
{
|
||||
struct file *file = get_fd_user( fd );
|
||||
|
||||
if (is_overlapped( file )) return FD_FLAG_OVERLAPPED;
|
||||
else return 0;
|
||||
*flags = 0;
|
||||
if (is_overlapped( file )) *flags |= FD_FLAG_OVERLAPPED;
|
||||
return FD_TYPE_FILE;
|
||||
}
|
||||
|
||||
static struct fd *file_get_fd( struct object *obj )
|
||||
|
|
|
@ -37,7 +37,7 @@ struct fd_ops
|
|||
/* flush the object buffers */
|
||||
int (*flush)(struct fd *, struct event **);
|
||||
/* get file information */
|
||||
int (*get_file_info)(struct fd *);
|
||||
enum server_fd_type (*get_file_info)(struct fd *fd, int *flags);
|
||||
/* queue an async operation */
|
||||
void (*queue_async)(struct fd *, void* apc, void* user, void* io_sb, int type, int count);
|
||||
/* cancel an async operation */
|
||||
|
@ -72,7 +72,7 @@ extern void fd_queue_async_timeout( struct fd *fd, void *apc, void *user, void *
|
|||
extern void default_fd_queue_async( struct fd *fd, void *apc, void *user, void *io_sb, int type, int count );
|
||||
extern void default_fd_cancel_async( struct fd *fd );
|
||||
extern int no_flush( struct fd *fd, struct event **event );
|
||||
extern int no_get_file_info( struct fd *fd );
|
||||
extern enum server_fd_type no_get_file_info( struct fd *fd, int *flags );
|
||||
extern void no_queue_async( struct fd *fd, void* apc, void* user, void* io_sb, int type, int count);
|
||||
extern void no_cancel_async( struct fd *fd );
|
||||
extern void main_loop(void);
|
||||
|
|
|
@ -84,7 +84,7 @@ static const struct object_ops mailslot_ops =
|
|||
mailslot_destroy /* destroy */
|
||||
};
|
||||
|
||||
static int mailslot_get_info( struct fd * );
|
||||
static enum server_fd_type mailslot_get_info( struct fd *fd, int *flags );
|
||||
static void mailslot_queue_async( struct fd *, void*, void*, void*, int, int );
|
||||
|
||||
static const struct fd_ops mailslot_fd_ops =
|
||||
|
@ -128,7 +128,7 @@ static const struct object_ops mail_writer_ops =
|
|||
mail_writer_destroy /* destroy */
|
||||
};
|
||||
|
||||
static int mail_writer_get_info( struct fd *fd );
|
||||
static enum server_fd_type mail_writer_get_info( struct fd *fd, int *flags );
|
||||
|
||||
static const struct fd_ops mail_writer_fd_ops =
|
||||
{
|
||||
|
@ -153,7 +153,7 @@ static struct fd *mailslot_device_get_fd( struct object *obj );
|
|||
static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name,
|
||||
unsigned int attr );
|
||||
static void mailslot_device_destroy( struct object *obj );
|
||||
static int mailslot_device_get_file_info( struct fd *fd );
|
||||
static enum server_fd_type mailslot_device_get_file_info( struct fd *fd, int *flags );
|
||||
|
||||
static const struct object_ops mailslot_device_ops =
|
||||
{
|
||||
|
@ -212,11 +212,12 @@ static int mailslot_message_count(struct mailslot *mailslot)
|
|||
return (poll( &pfd, 1, 0 ) == 1) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int mailslot_get_info( struct fd *fd )
|
||||
static enum server_fd_type mailslot_get_info( struct fd *fd, int *flags )
|
||||
{
|
||||
struct mailslot *mailslot = get_fd_user( fd );
|
||||
assert( mailslot->obj.ops == &mailslot_ops );
|
||||
return FD_FLAG_TIMEOUT | FD_FLAG_AVAILABLE;
|
||||
*flags = FD_FLAG_TIMEOUT | FD_FLAG_AVAILABLE;
|
||||
return FD_TYPE_MAILSLOT;
|
||||
}
|
||||
|
||||
static struct fd *mailslot_get_fd( struct object *obj )
|
||||
|
@ -298,9 +299,10 @@ static void mailslot_device_destroy( struct object *obj )
|
|||
free( device->mailslots );
|
||||
}
|
||||
|
||||
static int mailslot_device_get_file_info( struct fd *fd )
|
||||
static enum server_fd_type mailslot_device_get_file_info( struct fd *fd, int *flags )
|
||||
{
|
||||
return 0;
|
||||
*flags = 0;
|
||||
return FD_TYPE_DEVICE;
|
||||
}
|
||||
|
||||
void create_mailslot_device( struct directory *root, const struct unicode_str *name )
|
||||
|
@ -396,9 +398,10 @@ static void mail_writer_destroy( struct object *obj)
|
|||
release_object( writer->mailslot );
|
||||
}
|
||||
|
||||
static int mail_writer_get_info( struct fd *fd )
|
||||
static enum server_fd_type mail_writer_get_info( struct fd *fd, int *flags )
|
||||
{
|
||||
return 0;
|
||||
*flags = 0;
|
||||
return FD_TYPE_MAILSLOT;
|
||||
}
|
||||
|
||||
static struct fd *mail_writer_get_fd( struct object *obj )
|
||||
|
|
|
@ -134,7 +134,7 @@ static void pipe_server_dump( struct object *obj, int verbose );
|
|||
static struct fd *pipe_server_get_fd( struct object *obj );
|
||||
static void pipe_server_destroy( struct object *obj);
|
||||
static int pipe_server_flush( struct fd *fd, struct event **event );
|
||||
static int pipe_server_get_info( struct fd *fd );
|
||||
static enum server_fd_type pipe_server_get_info( struct fd *fd, int *flags );
|
||||
|
||||
static const struct object_ops pipe_server_ops =
|
||||
{
|
||||
|
@ -167,7 +167,7 @@ static void pipe_client_dump( struct object *obj, int verbose );
|
|||
static struct fd *pipe_client_get_fd( struct object *obj );
|
||||
static void pipe_client_destroy( struct object *obj );
|
||||
static int pipe_client_flush( struct fd *fd, struct event **event );
|
||||
static int pipe_client_get_info( struct fd *fd );
|
||||
static enum server_fd_type pipe_client_get_info( struct fd *fd, int *flags );
|
||||
|
||||
static const struct object_ops pipe_client_ops =
|
||||
{
|
||||
|
@ -200,7 +200,7 @@ static struct fd *named_pipe_device_get_fd( struct object *obj );
|
|||
static struct object *named_pipe_device_lookup_name( struct object *obj,
|
||||
struct unicode_str *name, unsigned int attr );
|
||||
static void named_pipe_device_destroy( struct object *obj );
|
||||
static int named_pipe_device_get_file_info( struct fd *fd );
|
||||
static enum server_fd_type named_pipe_device_get_file_info( struct fd *fd, int *flags );
|
||||
|
||||
static const struct object_ops named_pipe_device_ops =
|
||||
{
|
||||
|
@ -438,9 +438,10 @@ static void named_pipe_device_destroy( struct object *obj )
|
|||
free( device->pipes );
|
||||
}
|
||||
|
||||
static int named_pipe_device_get_file_info( struct fd *fd )
|
||||
static enum server_fd_type named_pipe_device_get_file_info( struct fd *fd, int *flags )
|
||||
{
|
||||
return 0;
|
||||
*flags = 0;
|
||||
return FD_TYPE_DEVICE;
|
||||
}
|
||||
|
||||
void create_named_pipe_device( struct directory *root, const struct unicode_str *name )
|
||||
|
@ -545,24 +546,22 @@ static inline int is_overlapped( unsigned int options )
|
|||
return !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
|
||||
}
|
||||
|
||||
static int pipe_server_get_info( struct fd *fd )
|
||||
static enum server_fd_type pipe_server_get_info( struct fd *fd, int *flags )
|
||||
{
|
||||
struct pipe_server *server = get_fd_user( fd );
|
||||
int flags = FD_FLAG_AVAILABLE;
|
||||
|
||||
if (is_overlapped( server->options )) flags |= FD_FLAG_OVERLAPPED;
|
||||
|
||||
return flags;
|
||||
*flags = FD_FLAG_AVAILABLE;
|
||||
if (is_overlapped( server->options )) *flags |= FD_FLAG_OVERLAPPED;
|
||||
return FD_TYPE_PIPE;
|
||||
}
|
||||
|
||||
static int pipe_client_get_info( struct fd *fd )
|
||||
static enum server_fd_type pipe_client_get_info( struct fd *fd, int *flags )
|
||||
{
|
||||
struct pipe_client *client = get_fd_user( fd );
|
||||
int flags = FD_FLAG_AVAILABLE;
|
||||
|
||||
if (is_overlapped( client->flags )) flags |= FD_FLAG_OVERLAPPED;
|
||||
|
||||
return flags;
|
||||
*flags = FD_FLAG_AVAILABLE;
|
||||
if (is_overlapped( client->flags )) *flags |= FD_FLAG_OVERLAPPED;
|
||||
return FD_TYPE_PIPE;
|
||||
}
|
||||
|
||||
static struct named_pipe *create_named_pipe( struct directory *root, const struct unicode_str *name,
|
||||
|
|
|
@ -661,8 +661,21 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
|
|||
unsigned int access; /* wanted access rights */
|
||||
int cached; /* is it cached on the client already? */
|
||||
@REPLY
|
||||
int type; /* file type (see below) */
|
||||
int flags; /* file read/write flags (see below) */
|
||||
@END
|
||||
enum server_fd_type
|
||||
{
|
||||
FD_TYPE_INVALID, /* invalid file (no associated fd) */
|
||||
FD_TYPE_FILE, /* regular file */
|
||||
FD_TYPE_DIR, /* directory */
|
||||
FD_TYPE_SOCKET, /* socket */
|
||||
FD_TYPE_SERIAL, /* serial port */
|
||||
FD_TYPE_PIPE, /* named pipe */
|
||||
FD_TYPE_MAILSLOT, /* mailslot */
|
||||
FD_TYPE_DEVICE, /* Windows device file */
|
||||
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
|
||||
|
|
|
@ -63,7 +63,7 @@ static void serial_destroy(struct object *obj);
|
|||
|
||||
static int serial_get_poll_events( struct fd *fd );
|
||||
static void serial_poll_event( struct fd *fd, int event );
|
||||
static int serial_get_info( struct fd *fd );
|
||||
static enum server_fd_type serial_get_info( struct fd *fd, int *flags );
|
||||
static int serial_flush( struct fd *fd, struct event **event );
|
||||
static void serial_queue_async( struct fd *fd, void *apc, void *user, void *iosb, int type, int count );
|
||||
static void serial_cancel_async( struct fd *fd );
|
||||
|
@ -205,22 +205,22 @@ static int serial_get_poll_events( struct fd *fd )
|
|||
return events;
|
||||
}
|
||||
|
||||
static int serial_get_info( struct fd *fd )
|
||||
static enum server_fd_type serial_get_info( struct fd *fd, int *flags )
|
||||
{
|
||||
int flags = 0;
|
||||
struct serial *serial = get_fd_user( fd );
|
||||
assert( serial->obj.ops == &serial_ops );
|
||||
|
||||
*flags = 0;
|
||||
if (!(serial->options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
|
||||
flags |= FD_FLAG_OVERLAPPED;
|
||||
*flags |= FD_FLAG_OVERLAPPED;
|
||||
else if (!(serial->readinterval == MAXDWORD &&
|
||||
serial->readmult == 0 && serial->readconst == 0))
|
||||
flags |= FD_FLAG_TIMEOUT;
|
||||
*flags |= FD_FLAG_TIMEOUT;
|
||||
if (serial->readinterval == MAXDWORD &&
|
||||
serial->readmult == 0 && serial->readconst == 0)
|
||||
flags |= FD_FLAG_AVAILABLE;
|
||||
*flags |= FD_FLAG_AVAILABLE;
|
||||
|
||||
return flags;
|
||||
return FD_TYPE_SERIAL;
|
||||
}
|
||||
|
||||
static void serial_poll_event(struct fd *fd, int event)
|
||||
|
|
|
@ -95,7 +95,7 @@ static void sock_destroy( struct object *obj );
|
|||
|
||||
static int sock_get_poll_events( struct fd *fd );
|
||||
static void sock_poll_event( struct fd *fd, int event );
|
||||
static int sock_get_info( struct fd *fd );
|
||||
static enum server_fd_type sock_get_info( struct fd *fd, int *flags );
|
||||
static void sock_queue_async( struct fd *fd, void *apc, void *user, void *iosb, int type, int count );
|
||||
static void sock_cancel_async( struct fd *fd );
|
||||
|
||||
|
@ -493,19 +493,19 @@ static int sock_get_poll_events( struct fd *fd )
|
|||
return ev;
|
||||
}
|
||||
|
||||
static int sock_get_info( struct fd *fd )
|
||||
static enum server_fd_type sock_get_info( struct fd *fd, int *flags )
|
||||
{
|
||||
int flags = FD_FLAG_AVAILABLE;
|
||||
struct sock *sock = get_fd_user( fd );
|
||||
assert( sock->obj.ops == &sock_ops );
|
||||
|
||||
if (sock->flags & WSA_FLAG_OVERLAPPED) flags |= FD_FLAG_OVERLAPPED;
|
||||
*flags = FD_FLAG_AVAILABLE;
|
||||
if (sock->flags & WSA_FLAG_OVERLAPPED) *flags |= FD_FLAG_OVERLAPPED;
|
||||
if ( sock->type != SOCK_STREAM || sock->state & FD_WINE_CONNECTED )
|
||||
{
|
||||
if ( !(sock->state & FD_READ ) ) flags |= FD_FLAG_RECV_SHUTDOWN;
|
||||
if ( !(sock->state & FD_WRITE ) ) flags |= FD_FLAG_SEND_SHUTDOWN;
|
||||
if ( !(sock->state & FD_READ ) ) *flags |= FD_FLAG_RECV_SHUTDOWN;
|
||||
if ( !(sock->state & FD_WRITE ) ) *flags |= FD_FLAG_SEND_SHUTDOWN;
|
||||
}
|
||||
return flags;
|
||||
return FD_TYPE_SOCKET;
|
||||
}
|
||||
|
||||
static void sock_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
|
||||
|
|
|
@ -1104,6 +1104,7 @@ static void dump_get_handle_fd_request( const struct get_handle_fd_request *req
|
|||
|
||||
static void dump_get_handle_fd_reply( const struct get_handle_fd_reply *req )
|
||||
{
|
||||
fprintf( stderr, " type=%d,", req->type );
|
||||
fprintf( stderr, " flags=%d", req->flags );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue