Commit f3fbae45 authored by Alexandre Julliard's avatar Alexandre Julliard

server: Allow specifying the status code to return on file descriptors that don't have a Unix fd.

parent 42cd970e
......@@ -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 );
}
}
}
......@@ -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,
......
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