From: Jinoh Kang jinoh.kang.kr@gmail.com
This is required to emulate Windows NT virtual file systems (e.g., \Device\NamedPipe).
In general, Windows file system drivers process pathnames on its own (for IRP_MJ_CREATE), since putting every existing file into the in-memory namespace is slow and highly inefficient.
To avoid regression, make the refactoring as close to no-op as possible. Some (subpath->len) checks could turn into an assert, but that seems highly superfluous and we don't know which are actually safe to do so. --- server/console.c | 99 ++++++++++++++++++++++++++++++++------------- server/device.c | 14 +++++-- server/fd.c | 6 +-- server/file.c | 14 +++++-- server/mailslot.c | 28 +++++++++---- server/named_pipe.c | 44 ++++++++++++++------ server/object.c | 9 +++-- server/object.h | 8 ++-- server/sock.c | 14 +++++-- 9 files changed, 163 insertions(+), 73 deletions(-)
diff --git a/server/console.c b/server/console.c index b64283baf4a..002a9b30a55 100644 --- a/server/console.c +++ b/server/console.c @@ -69,8 +69,8 @@ static int console_signaled( struct object *obj, struct wait_queue_entry *entry static struct fd *console_get_fd( struct object *obj ); static struct object *console_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attr, struct object *root ); -static struct object *console_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *console_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ); static int console_add_queue( struct object *obj, struct wait_queue_entry *entry );
static const struct object_ops console_ops = @@ -147,8 +147,8 @@ static int console_server_signaled( struct object *obj, struct wait_queue_entry static struct fd *console_server_get_fd( struct object *obj ); static struct object *console_server_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attr, struct object *root ); -static struct object *console_server_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *console_server_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options );
static const struct object_ops console_server_ops = { @@ -216,8 +216,8 @@ static void screen_buffer_dump( struct object *obj, int verbose ); static void screen_buffer_destroy( struct object *obj ); static int screen_buffer_add_queue( struct object *obj, struct wait_queue_entry *entry ); static struct fd *screen_buffer_get_fd( struct object *obj ); -static struct object *screen_buffer_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *screen_buffer_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options );
static const struct object_ops screen_buffer_ops = { @@ -265,8 +265,8 @@ static const struct fd_ops screen_buffer_fd_ops = static void console_device_dump( struct object *obj, int verbose ); static struct object *console_device_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attr, struct object *root ); -static struct object *console_device_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *console_device_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options );
static const struct object_ops console_device_ops = { @@ -299,8 +299,8 @@ struct console_input };
static void console_input_dump( struct object *obj, int verbose ); -static struct object *console_input_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *console_input_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ); static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry ); static struct fd *console_input_get_fd( struct object *obj ); static void console_input_destroy( struct object *obj ); @@ -358,8 +358,8 @@ struct console_output static void console_output_dump( struct object *obj, int verbose ); static int console_output_add_queue( struct object *obj, struct wait_queue_entry *entry ); static struct fd *console_output_get_fd( struct object *obj ); -static struct object *console_output_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *console_output_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ); static void console_output_destroy( struct object *obj );
static const struct object_ops console_output_ops = @@ -415,8 +415,8 @@ static void console_connection_dump( struct object *obj, int verbose ); static struct fd *console_connection_get_fd( struct object *obj ); static struct object *console_connection_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attr, struct object *root ); -static struct object *console_connection_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *console_connection_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ); static int console_connection_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void console_connection_destroy( struct object *obj );
@@ -805,9 +805,15 @@ static struct object *console_lookup_name( struct object *obj, struct unicode_st return NULL; }
-static struct object *console_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *console_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { + if (subpath->len) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + return grab_object( obj ); }
@@ -833,9 +839,15 @@ static void screen_buffer_destroy( struct object *obj ) free_async_queue( &screen_buffer->ioctl_q ); }
-static struct object *screen_buffer_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *screen_buffer_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { + if (subpath->len) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + return grab_object( obj ); }
@@ -920,9 +932,15 @@ static struct fd *console_server_get_fd( struct object* obj ) return (struct fd *)grab_object( server->fd ); }
-static struct object *console_server_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *console_server_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { + if (subpath->len) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + return grab_object( obj ); }
@@ -1230,9 +1248,15 @@ static struct object *console_connection_lookup_name( struct object *obj, struct return NULL; }
-static struct object *console_connection_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *console_connection_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { + if (subpath->len) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + return grab_object( obj ); }
@@ -1355,10 +1379,17 @@ static struct object *console_device_lookup_name( struct object *obj, struct uni return NULL; }
-static struct object *console_device_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *console_device_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { int is_output; + + if (subpath->len) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + access = default_map_access( obj, access ); is_output = access & FILE_WRITE_DATA; if (!current->process->console || (is_output && !current->process->console)) @@ -1396,9 +1427,15 @@ static struct fd *console_input_get_fd( struct object *obj ) return (struct fd *)grab_object( console_input->fd ); }
-static struct object *console_input_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *console_input_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { + if (subpath->len) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + return grab_object( obj ); }
@@ -1468,9 +1505,15 @@ static struct fd *console_output_get_fd( struct object *obj ) return (struct fd *)grab_object( console_output->fd ); }
-static struct object *console_output_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *console_output_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { + if (subpath->len) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + return grab_object( obj ); }
diff --git a/server/device.c b/server/device.c index 436dac6bfe9..32f8e217b86 100644 --- a/server/device.c +++ b/server/device.c @@ -151,8 +151,8 @@ struct device
static void device_dump( struct object *obj, int verbose ); static void device_destroy( struct object *obj ); -static struct object *device_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *device_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ); static struct list *device_get_kernel_obj_list( struct object *obj );
static const struct object_ops device_ops = @@ -420,13 +420,19 @@ static void add_irp_to_queue( struct device_manager *manager, struct irp_call *i if (list_head( &manager->requests ) == &irp->mgr_entry) wake_up( &manager->obj, 0 ); /* first one */ }
-static struct object *device_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *device_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { struct device *device = (struct device *)obj; struct device_file *file; struct unicode_str nt_name;
+ if (subpath->len) /* TODO: handle non-empty filenames (filesystem device) */ + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + if (!(file = alloc_object( &device_file_ops ))) return NULL;
file->device = (struct device *)grab_object( device ); diff --git a/server/fd.c b/server/fd.c index dabba024fb9..a39215a8d1e 100644 --- a/server/fd.c +++ b/server/fd.c @@ -2777,11 +2777,7 @@ DECL_HANDLER(open_file_object) if (root) release_object( root ); if (!obj) return;
- if (name_left.len) /* not fully parsed */ - { - set_error( STATUS_OBJECT_NAME_NOT_FOUND ); - } - else if ((result = obj->ops->open_file( obj, req->access, req->sharing, req->options ))) + if ((result = obj->ops->open_file( obj, &name_left, req->access, req->sharing, req->options ))) { reply->handle = alloc_handle( current->process, result, req->access, req->attributes ); release_object( result ); diff --git a/server/file.c b/server/file.c index 76c687833c9..6d2fc1e747a 100644 --- a/server/file.c +++ b/server/file.c @@ -79,8 +79,8 @@ static struct security_descriptor *file_get_sd( struct object *obj ); static int file_set_sd( struct object *obj, const struct security_descriptor *sd, unsigned int set_info ); static struct object *file_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attr, struct object *root ); -static struct object *file_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *file_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ); static struct list *file_get_kernel_obj_list( struct object *obj ); static void file_destroy( struct object *obj );
@@ -556,8 +556,8 @@ static struct object *file_lookup_name( struct object *obj, struct unicode_str * return NULL; }
-static struct object *file_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *file_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { struct file *file = (struct file *)obj; struct object *new_file = NULL; @@ -566,6 +566,12 @@ static struct object *file_open_file( struct object *obj, unsigned int access,
assert( obj->ops == &file_ops );
+ if (subpath->len) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + if ((unix_name = dup_fd_name( file->fd, "" ))) { get_nt_name( file->fd, &nt_name ); diff --git a/server/mailslot.c b/server/mailslot.c index 2d8697ec9bd..58e2b1a2ceb 100644 --- a/server/mailslot.c +++ b/server/mailslot.c @@ -62,8 +62,8 @@ static void mailslot_dump( struct object*, int ); static struct fd *mailslot_get_fd( struct object * ); static unsigned int mailslot_map_access( struct object *obj, unsigned int access ); static int mailslot_link_name( struct object *obj, struct object_name *name, struct object *parent ); -static struct object *mailslot_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *mailslot_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ); static void mailslot_destroy( struct object * );
static const struct object_ops mailslot_ops = @@ -184,8 +184,8 @@ struct mailslot_device_file static void mailslot_device_dump( struct object *obj, int verbose ); static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attr, struct object *root ); -static struct object *mailslot_device_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *mailslot_device_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ); static void mailslot_device_destroy( struct object *obj );
static const struct object_ops mailslot_device_ops = @@ -313,13 +313,19 @@ static int mailslot_link_name( struct object *obj, struct object_name *name, str return 1; }
-static struct object *mailslot_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *mailslot_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { struct mailslot *mailslot = (struct mailslot *)obj; struct mail_writer *writer; int unix_fd;
+ if (subpath->len) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + if (!(sharing & FILE_SHARE_READ)) { set_error( STATUS_SHARING_VIOLATION ); @@ -399,11 +405,17 @@ static struct object *mailslot_device_lookup_name( struct object *obj, struct un return found; }
-static struct object *mailslot_device_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *mailslot_device_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { struct mailslot_device_file *file;
+ if (subpath->len) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + if (!(file = alloc_object( &mailslot_device_file_ops ))) return NULL; file->device = (struct mailslot_device *)grab_object( obj ); if (!(file->fd = alloc_pseudo_fd( &mailslot_device_fd_ops, obj, options ))) diff --git a/server/named_pipe.c b/server/named_pipe.c index f3404a33c3b..e30bb4297fa 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -107,8 +107,8 @@ static void named_pipe_dump( struct object *obj, int verbose ); static unsigned int named_pipe_map_access( struct object *obj, unsigned int access ); static WCHAR *named_pipe_get_full_name( struct object *obj, data_size_t *ret_len ); static int named_pipe_link_name( struct object *obj, struct object_name *name, struct object *parent ); -static struct object *named_pipe_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *named_pipe_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ); static void named_pipe_destroy( struct object *obj );
static const struct object_ops named_pipe_ops = @@ -154,8 +154,8 @@ static void pipe_end_get_file_info( struct fd *fd, obj_handle_t handle, unsigned static void pipe_server_dump( struct object *obj, int verbose ); static struct object *pipe_server_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attr, struct object *root ); -static struct object *pipe_server_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *pipe_server_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ); static void pipe_server_destroy( struct object *obj); static void pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
@@ -246,8 +246,8 @@ static const struct fd_ops pipe_client_fd_ops = static void named_pipe_device_dump( struct object *obj, int verbose ); static struct object *named_pipe_device_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attr, struct object *root ); -static struct object *named_pipe_device_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *named_pipe_device_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ); static void named_pipe_device_destroy( struct object *obj );
static const struct object_ops named_pipe_device_ops = @@ -462,12 +462,18 @@ static struct object *pipe_server_lookup_name( struct object *obj, struct unicod return NULL; }
-static struct object *pipe_server_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *pipe_server_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { struct pipe_server *server = (struct pipe_server *)obj;
- return server->pipe_end.pipe->obj.ops->open_file( &server->pipe_end.pipe->obj, access, sharing, options ); + if (subpath->len) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + + return server->pipe_end.pipe->obj.ops->open_file( &server->pipe_end.pipe->obj, subpath, access, sharing, options ); }
static void pipe_server_destroy( struct object *obj ) @@ -508,11 +514,17 @@ static struct object *named_pipe_device_lookup_name( struct object *obj, struct return found; }
-static struct object *named_pipe_device_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *named_pipe_device_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { struct named_pipe_device_file *file;
+ if (subpath->len) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + if (!(file = alloc_object( &named_pipe_device_file_ops ))) return NULL; file->device = (struct named_pipe_device *)grab_object( obj ); if (!(file->fd = alloc_pseudo_fd( &named_pipe_device_fd_ops, obj, options ))) @@ -1333,14 +1345,20 @@ static int named_pipe_link_name( struct object *obj, struct object_name *name, s return 1; }
-static struct object *named_pipe_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *named_pipe_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { struct named_pipe *pipe = (struct named_pipe *)obj; struct pipe_server *server; struct pipe_end *client; unsigned int pipe_sharing;
+ if (subpath->len) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + if (list_empty( &pipe->listeners )) { set_error( STATUS_PIPE_NOT_AVAILABLE ); diff --git a/server/object.c b/server/object.c index 459ead5f3a5..20877cb129c 100644 --- a/server/object.c +++ b/server/object.c @@ -702,10 +702,13 @@ void default_unlink_name( struct object *obj, struct object_name *name ) list_remove( &name->entry ); }
-struct object *no_open_file( struct object *obj, unsigned int access, unsigned int sharing, - unsigned int options ) +struct object *no_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { - set_error( STATUS_OBJECT_TYPE_MISMATCH ); + if (subpath->len) /* not fully parsed */ + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + else + set_error( STATUS_OBJECT_TYPE_MISMATCH ); return NULL; }
diff --git a/server/object.h b/server/object.h index d4d66536b81..61221728f46 100644 --- a/server/object.h +++ b/server/object.h @@ -99,8 +99,8 @@ struct object_ops /* unlink an object's name from its parent */ void (*unlink_name)(struct object *, struct object_name *); /* open a file object to access this object */ - struct object *(*open_file)(struct object *, unsigned int access, unsigned int sharing, - unsigned int options); + struct object *(*open_file)(struct object *, const struct unicode_str *filename, + unsigned int access, unsigned int sharing, unsigned int options); /* return list of kernel objects */ struct list *(*get_kernel_obj_list)(struct object *); /* close a handle to this object */ @@ -178,8 +178,8 @@ extern struct object *no_lookup_name( struct object *obj, struct unicode_str *na unsigned int attributes, struct object *root ); extern int no_link_name( struct object *obj, struct object_name *name, struct object *parent ); extern void default_unlink_name( struct object *obj, struct object_name *name ); -extern struct object *no_open_file( struct object *obj, unsigned int access, unsigned int sharing, - unsigned int options ); +extern struct object *no_open_file( struct object *obj, const struct unicode_str *filename, unsigned int access, + unsigned int sharing, unsigned int options ); extern struct list *no_kernel_obj_list( struct object *obj ); extern int no_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); extern void no_destroy( struct object *obj ); diff --git a/server/sock.c b/server/sock.c index 8a95caded8b..e93ac95a7ea 100644 --- a/server/sock.c +++ b/server/sock.c @@ -3770,8 +3770,8 @@ static void sock_release_ifchange( struct sock *sock ) static void socket_device_dump( struct object *obj, int verbose ); static struct object *socket_device_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attr, struct object *root ); -static struct object *socket_device_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ); +static struct object *socket_device_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options );
static const struct object_ops socket_device_ops = { @@ -3809,11 +3809,17 @@ static struct object *socket_device_lookup_name( struct object *obj, struct unic return NULL; }
-static struct object *socket_device_open_file( struct object *obj, unsigned int access, - unsigned int sharing, unsigned int options ) +static struct object *socket_device_open_file( struct object *obj, const struct unicode_str *subpath, + unsigned int access, unsigned int sharing, unsigned int options ) { struct sock *sock;
+ if (subpath->len) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return NULL; + } + if (!(sock = create_socket())) return NULL; if (!(sock->fd = alloc_pseudo_fd( &sock_fd_ops, &sock->obj, options ))) {