From f3fbae4546597916cb4ebacc54597766f5894b08 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 18 Apr 2007 16:05:59 +0200 Subject: [PATCH] server: Allow specifying the status code to return on file descriptors that don't have a Unix fd. --- server/fd.c | 50 +++++++++++++++++++++----------------------------- server/file.h | 1 + 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/server/fd.c b/server/fd.c index d24eedc74a4..6372f4317d4 100644 --- a/server/fd.c +++ b/server/fd.c @@ -170,9 +170,9 @@ struct fd unsigned int options; /* file options (FILE_DELETE_ON_CLOSE, FILE_SYNCHRONOUS...) */ unsigned int sharing; /* file sharing mode */ int unix_fd; /* unix file descriptor */ + unsigned int no_fd_status;/* status to return when unix_fd is -1 */ int signaled :1; /* is the fd signaled? */ int fs_locks :1; /* can we use filesystem locks for this fd? */ - int unmounted :1;/* has the device been unmounted? */ int poll_index; /* index of fd in poll array */ struct async_queue *read_q; /* async readers of this fd */ struct async_queue *write_q; /* async writers of this fd */ @@ -1368,7 +1368,7 @@ static inline void unmount_fd( struct fd *fd ) if (fd->unix_fd != -1) close( fd->unix_fd ); fd->unix_fd = -1; - fd->unmounted = 1; + fd->no_fd_status = STATUS_VOLUME_DISMOUNTED; fd->closed->unix_fd = -1; fd->closed->unlink[0] = 0; @@ -1393,7 +1393,6 @@ static struct fd *alloc_fd_object(void) fd->unix_fd = -1; fd->signaled = 1; fd->fs_locks = 1; - fd->unmounted = 0; fd->poll_index = -1; fd->read_q = NULL; fd->write_q = NULL; @@ -1425,16 +1424,22 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use fd->unix_fd = -1; fd->signaled = 0; fd->fs_locks = 0; - fd->unmounted = 0; fd->poll_index = -1; fd->read_q = NULL; fd->write_q = NULL; fd->wait_q = NULL; + fd->no_fd_status = STATUS_BAD_DEVICE_TYPE; list_init( &fd->inode_entry ); list_init( &fd->locks ); return fd; } +/* set the status to return when the fd has no associated unix fd */ +void set_no_fd_status( struct fd *fd, unsigned int status ) +{ + fd->no_fd_status = status; +} + /* check if the desired access is possible without violating */ /* the sharing mode of other opens of the same file */ static int check_sharing( struct fd *fd, unsigned int access, unsigned int sharing ) @@ -1632,11 +1637,7 @@ unsigned int get_fd_options( struct fd *fd ) /* retrieve the unix fd for an object */ int get_unix_fd( struct fd *fd ) { - if (fd->unix_fd == -1) - { - if (fd->unmounted) set_error( STATUS_VOLUME_DISMOUNTED ); - else set_error( STATUS_BAD_DEVICE_TYPE ); - } + if (fd->unix_fd == -1) set_error( fd->no_fd_status ); return fd->unix_fd; } @@ -1932,19 +1933,15 @@ DECL_HANDLER(get_handle_fd) if ((fd = get_handle_fd_obj( current->process, req->handle, 0 ))) { - reply->type = fd->fd_ops->get_fd_type( fd ); - if (reply->type != FD_TYPE_INVALID) + int unix_fd = get_unix_fd( fd ); + if (unix_fd != -1) { - int unix_fd = get_unix_fd( fd ); - 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 ); - } + send_client_fd( current->process, unix_fd, req->handle ); + reply->type = fd->fd_ops->get_fd_type( fd ); + 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 ); release_object( fd ); } } @@ -1983,7 +1980,7 @@ DECL_HANDLER(register_async) if ((fd = get_handle_fd_obj( current->process, req->handle, access ))) { - fd->fd_ops->queue_async( fd, &req->async, req->type, req->count ); + if (get_unix_fd( fd ) != -1) fd->fd_ops->queue_async( fd, &req->async, req->type, req->count ); release_object( fd ); } } @@ -1992,15 +1989,10 @@ DECL_HANDLER(register_async) DECL_HANDLER(cancel_async) { struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 ); + if (fd) { - /* Note: we don't kill the queued APC_ASYNC_IO on this thread because - * NtCancelIoFile() will force the pending APC to be run. Since, - * Windows only guarantees that the current thread will have no async - * operation on the current fd when NtCancelIoFile returns, this shall - * do the work. - */ - fd->fd_ops->cancel_async( fd ); + if (get_unix_fd( fd ) != -1) fd->fd_ops->cancel_async( fd ); release_object( fd ); - } + } } diff --git a/server/file.h b/server/file.h index 262a011e705..09c90c3c311 100644 --- a/server/file.h +++ b/server/file.h @@ -53,6 +53,7 @@ struct fd_ops /* file descriptor functions */ extern struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *user ); +extern void set_no_fd_status( struct fd *fd, unsigned int status ); extern struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int access, unsigned int sharing, unsigned int options ); extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops, -- 2.11.4.GIT